* [v3 PATCH] PR libstdc++/80675, PR libstdc++/80940
@ 2017-06-10 1:38 Ville Voutilainen
2017-06-15 11:01 ` Jonathan Wakely
0 siblings, 1 reply; 2+ messages in thread
From: Ville Voutilainen @ 2017-06-10 1:38 UTC (permalink / raw)
To: libstdc++, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 1138 bytes --]
Tested on Linux-x64.
2017-06-10 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.
[-- Attachment #2: 80675_80940.diff --]
[-- Type: text/plain, Size: 7318 bytes --]
diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream
index 85c0a5a..86a5d03 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_same<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 50b70a5..cffcd06 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_same<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
diff --git a/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc b/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc
index 2b46aa1..9c20274 100644
--- a/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc
+++ b/libstdc++-v3/testsuite/27_io/rvalue_streams-2.cc
@@ -24,11 +24,64 @@ struct A {};
void operator<<(std::ostream&, const 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++/80675
+// PR libstdc++/80940
int main()
{
A a;
std::ostringstream() << a;
std::istringstream() >> a;
+ MyStream stream{};
+ stream << "aaa";
+ int msi;
+ stream >> msi;
+ MyStream2 stream2{};
+ stream2 << "aaa";
+ stream2 >> msi;
+ O{} << X{};
+ I{} >> X{};
}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [v3 PATCH] PR libstdc++/80675, PR libstdc++/80940
2017-06-10 1:38 [v3 PATCH] PR libstdc++/80675, PR libstdc++/80940 Ville Voutilainen
@ 2017-06-15 11:01 ` Jonathan Wakely
0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2017-06-15 11:01 UTC (permalink / raw)
To: Ville Voutilainen; +Cc: libstdc++, gcc-patches
On 10/06/17 04:38 +0300, Ville Voutilainen wrote:
>- 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_same<void,
>+ typename __is_convertible_to_basic_istream_impl<_Tp>::__istream_type>>;
This could use is_void<...> instead of is_same<void, ...>, same below.
Otherwise OK for trunk, thanks for dealing with this.
80940 is a regression, so we need this on gcc-7-branch too, assuming
it passes testing there.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-06-15 11:01 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-06-10 1:38 [v3 PATCH] PR libstdc++/80675, PR libstdc++/80940 Ville Voutilainen
2017-06-15 11:01 ` 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).