diff --git a/stl/inc/istream b/stl/inc/istream index d70df7689c4..c9c10b07cf4 100644 --- a/stl/inc/istream +++ b/stl/inc/istream @@ -876,9 +876,7 @@ template struct _Can_stream_in<_Istr, _Ty, void_t() >> _STD declval<_Ty>())>> : true_type {}; template >, is_base_of, _Can_stream_in<_Istr, _Ty>>, - int> = 0> + enable_if_t, _Can_stream_in<_Istr, _Ty>>, int> = 0> _Istr&& operator>>(_Istr&& _Is, _Ty&& _Val) { // extract from rvalue stream _Is >> _STD forward<_Ty>(_Val); return _STD move(_Is); diff --git a/stl/inc/ostream b/stl/inc/ostream index 95ad3889a71..671f8d0e0bd 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -966,9 +966,7 @@ struct _Can_stream_out<_Ostr, _Ty, void_t() << _ST }; template >, is_base_of, _Can_stream_out<_Ostr, _Ty>>, - int> = 0> + enable_if_t, _Can_stream_out<_Ostr, _Ty>>, int> = 0> _Ostr&& operator<<(_Ostr&& _Os, const _Ty& _Val) { // insert to rvalue stream _Os << _Val; return _STD move(_Os); diff --git a/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp b/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp index fcb39728845..3646a6e51b9 100644 --- a/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp +++ b/tests/std/tests/VSO_0000000_nullptr_stream_out/test.cpp @@ -2,11 +2,35 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include +#include +#include #include #include - +#include +#include using namespace std; +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template +constexpr bool IstreamExtractable = false; +template +constexpr bool IstreamExtractable() >> declval())>> = true; + +class PublicIstream : public istream {}; +class PrivateIstream : private istream {}; +PrivateIstream& operator>>(PrivateIstream&, int&); // highly artificial test code, see below + +template +constexpr bool OstreamInsertable = false; +template +constexpr bool OstreamInsertable() << declval())>> = true; + +class PublicOstream : public ostream {}; +class PrivateOstream : private ostream {}; +PrivateOstream& operator<<(PrivateOstream&, int); // highly artificial test code, see below + int main() { #if _HAS_CXX17 // LWG-2221 "No formatted output operator for nullptr" @@ -23,4 +47,21 @@ int main() { int x; assert((istringstream("42 1729") >> x).str() == "42 1729"); assert(x == 42); + + // Test GH-538 by verifying that LWG-1203 is constrained by "publicly and unambiguously derived". + // The "highly artificial" operator overloads above are ensuring that the streaming expressions are well-formed + // for lvalue PrivateIstream/PrivateOstream, so we can specifically test the inheritance constraint. + STATIC_ASSERT(IstreamExtractable); + STATIC_ASSERT(IstreamExtractable); + STATIC_ASSERT(IstreamExtractable); + STATIC_ASSERT(IstreamExtractable); + STATIC_ASSERT(IstreamExtractable); + STATIC_ASSERT(!IstreamExtractable); + + STATIC_ASSERT(OstreamInsertable); + STATIC_ASSERT(OstreamInsertable); + STATIC_ASSERT(OstreamInsertable); + STATIC_ASSERT(OstreamInsertable); + STATIC_ASSERT(OstreamInsertable); + STATIC_ASSERT(!OstreamInsertable); }