@@ -953,57 +953,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
ws(basic_istream<_CharT, _Traits>& __is);
#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>
- 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>>>
- {
- using __istream_type =
- __do_is_convertible_to_basic_istream_impl<_Tp>;
- };
-
- template<typename _Tp>
- struct __is_convertible_to_basic_istream
- : __is_convertible_to_basic_istream_impl<_Tp>
- {
- public:
- using type = __not_<is_void<
- typename __is_convertible_to_basic_istream_impl<_Tp>::__istream_type>>;
- constexpr static bool value = type::value;
- };
-
- template<typename _Istream, typename _Tp, typename = void>
- struct __is_extractable : false_type {};
-
- template<typename _Istream, typename _Tp>
- struct __is_extractable<_Istream, _Tp,
- __void_t<decltype(declval<_Istream&>()
- >> declval<_Tp>())>>
- : 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
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 2328. Rvalue stream extraction should use perfect forwarding
+ // 1203. More useful rvalue stream insertion
/**
* @brief Generic extractor for rvalue stream
* @param __is An input stream.
@@ -1015,18 +968,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* that take an lvalue reference.
*/
template<typename _Istream, typename _Tp>
- inline
- typename enable_if<__and_<__not_<is_lvalue_reference<_Istream>>,
- __is_convertible_to_basic_istream<_Istream>,
- __is_extractable<
- __rvalue_istream_type<_Istream>,
- _Tp&&>>::value,
- __rvalue_istream_type<_Istream>>::type
+ inline auto
operator>>(_Istream&& __is, _Tp&& __x)
+ -> __enable_if_t<is_convertible<_Istream*, ios_base*>::value,
+ decltype(void(__is >> std::declval<_Tp>()),
+ std::declval<_Istream&&>())>
{
- __rvalue_istream_type<_Istream> __ret_is = __is;
- __ret_is >> std::forward<_Tp>(__x);
- return __ret_is;
+ __is >> std::forward<_Tp>(__x);
+ return std::move(__is);
}
#endif // C++11
@@ -704,54 +704,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __os.flush(); }
#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>
- struct __is_convertible_to_basic_ostream
- : __is_convertible_to_basic_ostream_impl<_Tp>
- {
- public:
- using type = __not_<is_void<
- typename __is_convertible_to_basic_ostream_impl<_Tp>::__ostream_type>>;
- constexpr static bool value = type::value;
- };
-
- template<typename _Ostream, typename _Tp, typename = void>
- struct __is_insertable : false_type {};
-
- template<typename _Ostream, typename _Tp>
- struct __is_insertable<_Ostream, _Tp,
- __void_t<decltype(declval<_Ostream&>()
- << declval<const _Tp&>())>>
- : true_type {};
-
- template<typename _Ostream>
- using __rvalue_ostream_type =
- typename __is_convertible_to_basic_ostream<
- _Ostream>::__ostream_type;
-
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 1203. More useful rvalue stream insertion
/**
* @brief Generic inserter for rvalue stream
* @param __os An input stream.
@@ -763,18 +717,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
* that take an lvalue reference.
*/
template<typename _Ostream, typename _Tp>
- inline
- typename enable_if<__and_<__not_<is_lvalue_reference<_Ostream>>,
- __is_convertible_to_basic_ostream<_Ostream>,
- __is_insertable<
- __rvalue_ostream_type<_Ostream>,
- const _Tp&>>::value,
- __rvalue_ostream_type<_Ostream>>::type
+ inline auto
operator<<(_Ostream&& __os, const _Tp& __x)
+ -> __enable_if_t<is_convertible<_Ostream*, ios_base*>::value,
+ decltype(void(__os << __x), std::declval<_Ostream&&>())>
{
- __rvalue_ostream_type<_Ostream> __ret_os = __os;
- __ret_os << __x;
- return __ret_os;
+ __os << __x;
+ return std::move(__os);
}
#if __cplusplus > 201703L && _GLIBCXX_USE_CXX11_ABI
@@ -25,8 +25,6 @@ void
test01()
{
int i = 1742;
- // This usage isn't supported by the current draft.
- // std::string result = (std::ostringstream() << i).str();
std::ostringstream() << i;
std::string result ("1742");
int i2;
@@ -45,10 +43,10 @@ test02()
{
X x;
std::istringstream is;
- auto& ref1 = (std::move(is) >> x);
+ auto&& ref1 = (std::move(is) >> x);
VERIFY( &ref1 == &is );
VERIFY( x.as_rvalue == false );
- auto& ref2 = (std::move(is) >> std::move(x));
+ auto&& ref2 = (std::move(is) >> std::move(x));
VERIFY( &ref2 == &is );
VERIFY( x.as_rvalue == true );
@@ -57,6 +55,36 @@ test02()
std::istringstream("x") >> &arr[0];
#endif
std::istringstream("x") >> arr;
+ VERIFY( std::string(arr) == "x" );
+}
+
+// LWG 1203 More useful rvalue stream insertion
+void
+test03()
+{
+ int i = 1203;
+ std::string result = (std::ostringstream() << "i = " << i).str();
+ VERIFY( result == "i = 1203" );
+
+ std::ostringstream os;
+ std::ostringstream&& ros = std::move(os) << result;
+ VERIFY( &ros == &os );
+ VERIFY( ros.str() == result );
+
+ std::stringstream ss;
+ std::stringstream&& rss = std::move(ss) << result;
+ VERIFY( &rss == &ss );
+ VERIFY( rss.str() == result );
+
+ std::istringstream is("first second third");
+ std::istringstream&& ris = std::move(is) >> result;
+ VERIFY( &ris == &is );
+ VERIFY( result == "first" );
+
+ std::stringstream ss2("fourth fifth sixth");
+ std::stringstream&& rss2 = std::move(ss2) >> result;
+ VERIFY( &rss2 == &ss2 );
+ VERIFY( result == "fourth" );
}
int
@@ -64,5 +92,5 @@ main()
{
test01();
test02();
- return 0;
+ test03();
}