Commit 5e88d2d0 by Ville Voutilainen Committed by Ville Voutilainen

PR libstdc++/80675, PR libstdc++/80940

* include/std/istream:
(__is_convertible_to_basic_istream_test(basic_istream<_Ch, _Up>*)): New.
(__do_is_convertible_to_basic_istream_impl): Likewise.
(__is_convertible_to_basic_istream_impl): Likewise.
(__is_convertible_to_basic_istream): Use the new base.
(__rvalue_istream_type): New.
(operator>>(_Istream&&, _Tp&&)): Use the new helper alias
for the SFINAE check, convert to the helper alias type before
doing the actual extraction.
* include/std/ostream:
(__is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*)): New.
(__do_is_convertible_to_basic_ostream_impl): Likewise.
(__is_convertible_to_basic_ostream_impl): Likewise.
(__is_convertible_to_basic_ostream): Use the new base.
(__rvalue_ostream_type): New.
(operator<<(_Ostream&&, const _Tp&)): Use the new helper alias
for the SFINAE check, convert to the helper alias type before
doing the actual insertion.
* testsuite/27_io/rvalue_streams-2.cc: Add new tests.

From-SVN: r249468
parent cb8d1b01
2017-06-21 Ville Voutilainen <ville.voutilainen@gmail.com>
PR libstdc++/80675
PR libstdc++/80940
* include/std/istream:
(__is_convertible_to_basic_istream_test(basic_istream<_Ch, _Up>*)): New.
(__do_is_convertible_to_basic_istream_impl): Likewise.
(__is_convertible_to_basic_istream_impl): Likewise.
(__is_convertible_to_basic_istream): Use the new base.
(__rvalue_istream_type): New.
(operator>>(_Istream&&, _Tp&&)): Use the new helper alias
for the SFINAE check, convert to the helper alias type before
doing the actual extraction.
* include/std/ostream:
(__is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*)): New.
(__do_is_convertible_to_basic_ostream_impl): Likewise.
(__is_convertible_to_basic_ostream_impl): Likewise.
(__is_convertible_to_basic_ostream): Use the new base.
(__rvalue_ostream_type): New.
(operator<<(_Ostream&&, const _Tp&)): Use the new helper alias
for the SFINAE check, convert to the helper alias type before
doing the actual insertion.
* testsuite/27_io/rvalue_streams-2.cc: Add new tests.
2017-06-21 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> 2017-06-21 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
* config/abi/post/aarch64-linux-gnu/baseline_symbols.txt: Update. * config/abi/post/aarch64-linux-gnu/baseline_symbols.txt: Update.
......
...@@ -908,20 +908,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -908,20 +908,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
ws(basic_istream<_CharT, _Traits>& __is); ws(basic_istream<_CharT, _Traits>& __is);
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename _Ch, typename _Up>
basic_istream<_Ch, _Up>&
__is_convertible_to_basic_istream_test(basic_istream<_Ch, _Up>*);
template<typename _Tp, typename = void>
struct __is_convertible_to_basic_istream_impl
{
using __istream_type = void;
};
template<typename _Tp> template<typename _Tp>
struct __is_convertible_to_basic_istream using __do_is_convertible_to_basic_istream_impl =
decltype(__is_convertible_to_basic_istream_test
(declval<typename remove_reference<_Tp>::type*>()));
template<typename _Tp>
struct __is_convertible_to_basic_istream_impl
<_Tp,
__void_t<__do_is_convertible_to_basic_istream_impl<_Tp>>>
{ {
template<typename _Ch, typename _Up> using __istream_type =
static basic_istream<_Ch, _Up>& __check(basic_istream<_Ch, _Up>*); __do_is_convertible_to_basic_istream_impl<_Tp>;
};
static void __check(...); template<typename _Tp>
struct __is_convertible_to_basic_istream
: __is_convertible_to_basic_istream_impl<_Tp>
{
public: public:
using istream_type = using type = __not_<is_void<
decltype(__check(declval<typename remove_reference<_Tp>::type*>())); typename __is_convertible_to_basic_istream_impl<_Tp>::__istream_type>>;
using type = __not_<is_same<istream_type, void>>;
constexpr static bool value = type::value; constexpr static bool value = type::value;
}; };
template<typename _Istream, typename _Tp, typename = void> template<typename _Istream, typename _Tp, typename = void>
struct __is_extractable : false_type {}; struct __is_extractable : false_type {};
...@@ -932,6 +951,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -932,6 +951,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> declval<_Tp>())>> >> declval<_Tp>())>>
: true_type {}; : true_type {};
template<typename _Istream>
using __rvalue_istream_type =
typename __is_convertible_to_basic_istream<
_Istream>::__istream_type;
// [27.7.1.6] Rvalue stream extraction // [27.7.1.6] Rvalue stream extraction
// _GLIBCXX_RESOLVE_LIB_DEFECTS // _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2328. Rvalue stream extraction should use perfect forwarding // 2328. Rvalue stream extraction should use perfect forwarding
...@@ -949,13 +973,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -949,13 +973,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline inline
typename enable_if<__and_<__not_<is_lvalue_reference<_Istream>>, typename enable_if<__and_<__not_<is_lvalue_reference<_Istream>>,
__is_convertible_to_basic_istream<_Istream>, __is_convertible_to_basic_istream<_Istream>,
__is_extractable<_Istream&, _Tp&&>>::value, __is_extractable<
typename __is_convertible_to_basic_istream< __rvalue_istream_type<_Istream>,
_Istream>::istream_type>::type _Tp&&>>::value,
__rvalue_istream_type<_Istream>>::type
operator>>(_Istream&& __is, _Tp&& __x) operator>>(_Istream&& __is, _Tp&& __x)
{ {
__is >> std::forward<_Tp>(__x); __rvalue_istream_type<_Istream> __ret_is = __is;
return __is; __ret_is >> std::forward<_Tp>(__x);
return __ret_is;
} }
#endif // C++11 #endif // C++11
......
...@@ -613,19 +613,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -613,19 +613,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __os.flush(); } { return __os.flush(); }
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
template<typename _Ch, typename _Up>
basic_ostream<_Ch, _Up>&
__is_convertible_to_basic_ostream_test(basic_ostream<_Ch, _Up>*);
template<typename _Tp, typename = void>
struct __is_convertible_to_basic_ostream_impl
{
using __ostream_type = void;
};
template<typename _Tp>
using __do_is_convertible_to_basic_ostream_impl =
decltype(__is_convertible_to_basic_ostream_test
(declval<typename remove_reference<_Tp>::type*>()));
template<typename _Tp>
struct __is_convertible_to_basic_ostream_impl
<_Tp,
__void_t<__do_is_convertible_to_basic_ostream_impl<_Tp>>>
{
using __ostream_type =
__do_is_convertible_to_basic_ostream_impl<_Tp>;
};
template<typename _Tp> template<typename _Tp>
struct __is_convertible_to_basic_ostream struct __is_convertible_to_basic_ostream
{ : __is_convertible_to_basic_ostream_impl<_Tp>
template<typename _Ch, typename _Up> {
static basic_ostream<_Ch, _Up>& __check(basic_ostream<_Ch, _Up>*); public:
using type = __not_<is_void<
static void __check(...); typename __is_convertible_to_basic_ostream_impl<_Tp>::__ostream_type>>;
public: constexpr static bool value = type::value;
using ostream_type = };
decltype(__check(declval<typename remove_reference<_Tp>::type*>()));
using type = __not_<is_same<ostream_type, void>>;
constexpr static bool value = type::value;
};
template<typename _Ostream, typename _Tp, typename = void> template<typename _Ostream, typename _Tp, typename = void>
struct __is_insertable : false_type {}; struct __is_insertable : false_type {};
...@@ -636,6 +656,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -636,6 +656,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
<< declval<const _Tp&>())>> << declval<const _Tp&>())>>
: true_type {}; : true_type {};
template<typename _Ostream>
using __rvalue_ostream_type =
typename __is_convertible_to_basic_ostream<
_Ostream>::__ostream_type;
/** /**
* @brief Generic inserter for rvalue stream * @brief Generic inserter for rvalue stream
* @param __os An input stream. * @param __os An input stream.
...@@ -650,13 +675,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -650,13 +675,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
inline inline
typename enable_if<__and_<__not_<is_lvalue_reference<_Ostream>>, typename enable_if<__and_<__not_<is_lvalue_reference<_Ostream>>,
__is_convertible_to_basic_ostream<_Ostream>, __is_convertible_to_basic_ostream<_Ostream>,
__is_insertable<_Ostream&, const _Tp&>>::value, __is_insertable<
typename __is_convertible_to_basic_ostream< __rvalue_ostream_type<_Ostream>,
_Ostream>::ostream_type>::type const _Tp&>>::value,
__rvalue_ostream_type<_Ostream>>::type
operator<<(_Ostream&& __os, const _Tp& __x) operator<<(_Ostream&& __os, const _Tp& __x)
{ {
__os << __x; __rvalue_ostream_type<_Ostream> __ret_os = __os;
return __os; __ret_os << __x;
return __ret_os;
} }
#endif // C++11 #endif // C++11
......
...@@ -24,11 +24,64 @@ struct A {}; ...@@ -24,11 +24,64 @@ struct A {};
void operator<<(std::ostream&, const A&) { } void operator<<(std::ostream&, const A&) { }
void operator>>(std::istream&, A&) { } void operator>>(std::istream&, A&) { }
class MyStream : private std::ostream, private std::istream
{
public:
MyStream& operator <<(const char*)
{
return *this;
}
MyStream& operator >>(int&)
{
return *this;
}
};
class MyStream2
{
public:
MyStream2& operator <<(const char*)
{
return *this;
}
MyStream2& operator >>(int&)
{
return *this;
}
private:
operator std::ostream&();
operator std::istream&();
};
struct X { };
std::ostream& operator<<(std::ostream& os, const X&) { return os; }
std::istream& operator>>(std::istream& is, X&&) { return is; }
struct O : std::ostream { };
void operator<<(O&, X) = delete;
struct I : std::istream { };
void operator>>(I&, X) = delete;
// PR libstdc++/65543 // PR libstdc++/65543
// PR libstdc++/80675
// PR libstdc++/80940
int main() int main()
{ {
A a; A a;
std::ostringstream() << a; std::ostringstream() << a;
std::istringstream() >> a; std::istringstream() >> a;
MyStream stream{};
stream << "aaa";
int msi;
stream >> msi;
MyStream2 stream2{};
stream2 << "aaa";
stream2 >> msi;
O{} << X{};
I{} >> X{};
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment