diff options
author | Ville Voutilainen <ville.voutilainen@gmail.com> | 2017-06-21 22:53:26 +0300 |
---|---|---|
committer | Ville Voutilainen <ville@gcc.gnu.org> | 2017-06-21 22:53:26 +0300 |
commit | 5e88d2d08d464d80bbe5dfd64db954f2dd516b7e (patch) | |
tree | 682442a25a4dfb8a09356142015098db8fe62801 /libstdc++-v3/include | |
parent | cb8d1b01b3a2198c67d04a3a077bc7c55aaaa31c (diff) | |
download | gcc-5e88d2d08d464d80bbe5dfd64db954f2dd516b7e.tar.gz |
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
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/std/istream | 52 | ||||
-rw-r--r-- | libstdc++-v3/include/std/ostream | 59 |
2 files changed, 82 insertions, 29 deletions
diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream index 85c0a5a2f42..1fa25555771 100644 --- a/libstdc++-v3/include/std/istream +++ b/libstdc++-v3/include/std/istream @@ -908,20 +908,39 @@ _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> - 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> - static basic_istream<_Ch, _Up>& __check(basic_istream<_Ch, _Up>*); + using __istream_type = + __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: - using istream_type = - decltype(__check(declval<typename remove_reference<_Tp>::type*>())); - using type = __not_<is_same<istream_type, void>>; + 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 {}; @@ -932,6 +951,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> 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 @@ -949,13 +973,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename enable_if<__and_<__not_<is_lvalue_reference<_Istream>>, __is_convertible_to_basic_istream<_Istream>, - __is_extractable<_Istream&, _Tp&&>>::value, - typename __is_convertible_to_basic_istream< - _Istream>::istream_type>::type + __is_extractable< + __rvalue_istream_type<_Istream>, + _Tp&&>>::value, + __rvalue_istream_type<_Istream>>::type operator>>(_Istream&& __is, _Tp&& __x) { - __is >> std::forward<_Tp>(__x); - return __is; + __rvalue_istream_type<_Istream> __ret_is = __is; + __ret_is >> std::forward<_Tp>(__x); + return __ret_is; } #endif // C++11 diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream index 50b70a5080c..f7cab03c841 100644 --- a/libstdc++-v3/include/std/ostream +++ b/libstdc++-v3/include/std/ostream @@ -613,19 +613,39 @@ _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 - { - template<typename _Ch, typename _Up> - static basic_ostream<_Ch, _Up>& __check(basic_ostream<_Ch, _Up>*); - - static void __check(...); - public: - 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; - }; + : __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 {}; @@ -636,6 +656,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION << declval<const _Tp&>())>> : true_type {}; + template<typename _Ostream> + using __rvalue_ostream_type = + typename __is_convertible_to_basic_ostream< + _Ostream>::__ostream_type; + /** * @brief Generic inserter for rvalue stream * @param __os An input stream. @@ -650,13 +675,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline typename enable_if<__and_<__not_<is_lvalue_reference<_Ostream>>, __is_convertible_to_basic_ostream<_Ostream>, - __is_insertable<_Ostream&, const _Tp&>>::value, - typename __is_convertible_to_basic_ostream< - _Ostream>::ostream_type>::type + __is_insertable< + __rvalue_ostream_type<_Ostream>, + const _Tp&>>::value, + __rvalue_ostream_type<_Ostream>>::type operator<<(_Ostream&& __os, const _Tp& __x) { - __os << __x; - return __os; + __rvalue_ostream_type<_Ostream> __ret_os = __os; + __ret_os << __x; + return __ret_os; } #endif // C++11 |