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
This commit is contained in:
Ville Voutilainen 2017-06-21 22:53:26 +03:00 committed by Ville Voutilainen
parent cb8d1b01b3
commit 5e88d2d08d
4 changed files with 159 additions and 29 deletions

View file

@ -1,3 +1,27 @@
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>
* config/abi/post/aarch64-linux-gnu/baseline_symbols.txt: Update.

View file

@ -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>
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>
{
template<typename _Ch, typename _Up>
static basic_istream<_Ch, _Up>& __check(basic_istream<_Ch, _Up>*);
static void __check(...);
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

View file

@ -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

View file

@ -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{};
}