public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [stage1 PATCH] libstdc++: Implement LWG 1203 for rvalue iostreams
@ 2021-03-17 18:33 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2021-03-17 18:33 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 502 bytes --]

This implements the resolution of LWG 1203 so that the constraints for
rvalue stream insertion/extraction are simpler, and the return type is
the original rvalue stream type not its base class.

libstdc++-v3/ChangeLog:

	* include/std/istream (operator>>(Ostream&&, x&)): Simplify, as
	per LWG 1203.
	* include/std/ostream (operator<<(Ostream&&, const x&)):
	Likewise.
	* testsuite/27_io/rvalue_streams.cc: Adjust existing test.
	Verify LWG 1203 changes.

Tested, but I won't push this until stage 1.


[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 8474 bytes --]

commit 83317035b13965ae76bc81b27ba62d8300eb9377
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Mar 17 18:17:15 2021

    libstdc++: Implement LWG 1203 for rvalue iostreams
    
    This implements the resolution of LWG 1203 so that the constraints for
    rvalue stream insertion/extraction are simpler, and the return type is
    the original rvalue stream type not its base class.
    
    libstdc++-v3/ChangeLog:
    
            * include/std/istream (operator>>(Ostream&&, x&)): Simplify, as
            per LWG 1203.
            * include/std/ostream (operator<<(Ostream&&, const x&)):
            Likewise.
            * testsuite/27_io/rvalue_streams.cc: Adjust existing test.
            Verify LWG 1203 changes.

diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream
index 24235c9b6c8..626bc797b58 100644
--- a/libstdc++-v3/include/std/istream
+++ b/libstdc++-v3/include/std/istream
@@ -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
 
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index c7c4e78e8a7..f24927b80d9 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -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
diff --git a/libstdc++-v3/testsuite/27_io/rvalue_streams.cc b/libstdc++-v3/testsuite/27_io/rvalue_streams.cc
index def706999a3..be240698abf 100644
--- a/libstdc++-v3/testsuite/27_io/rvalue_streams.cc
+++ b/libstdc++-v3/testsuite/27_io/rvalue_streams.cc
@@ -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();
 }

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-03-17 18:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-17 18:33 [stage1 PATCH] libstdc++: Implement LWG 1203 for rvalue iostreams Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).