[libcxx-commits] [libcxx] c90dee1 - [libc++] Re-apply fdc41e11f (LWG1203) without breaking the C++11 build
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Sep 23 05:56:09 PDT 2020
Author: Louis Dionne
Date: 2020-09-23T08:56:00-04:00
New Revision: c90dee1e90045feb039be640864f038eebd1d8cd
URL: https://github.com/llvm/llvm-project/commit/c90dee1e90045feb039be640864f038eebd1d8cd
DIFF: https://github.com/llvm/llvm-project/commit/c90dee1e90045feb039be640864f038eebd1d8cd.diff
LOG: [libc++] Re-apply fdc41e11f (LWG1203) without breaking the C++11 build
fdc41e11f was reverted in e46c1def5 because it broke the C++11 build.
We shouldn't be using enable_if_t in C++11, instead we must use
enable_if<...>::type.
Added:
libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/not_istreamable.verify.cpp
libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/not_ostreamable.verify.cpp
libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/rvalue.pass.cpp
Modified:
libcxx/include/istream
libcxx/include/ostream
libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/rvalue.pass.cpp
libcxx/www/cxx2a_status.html
Removed:
libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/CharT_pointer.pass.cpp
################################################################################
diff --git a/libcxx/include/istream b/libcxx/include/istream
index bfbe5f24728e..16653e55f4dd 100644
--- a/libcxx/include/istream
+++ b/libcxx/include/istream
@@ -150,9 +150,9 @@ template <class charT, class traits>
basic_istream<charT,traits>&
ws(basic_istream<charT,traits>& is);
-template <class charT, class traits, class T>
- basic_istream<charT, traits>&
- operator>>(basic_istream<charT, traits>&& is, T& x);
+// rvalue stream extraction
+template <class Stream, class T>
+ Stream&& operator>>(Stream&& is, T&& x);
} // std
@@ -1378,13 +1378,23 @@ ws(basic_istream<_CharT, _Traits>& __is)
#ifndef _LIBCPP_CXX03_LANG
-template <class _CharT, class _Traits, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-basic_istream<_CharT, _Traits>&
-operator>>(basic_istream<_CharT, _Traits>&& __is, _Tp&& __x)
+template <class _Stream, class _Tp, class = void>
+struct __is_istreamable : false_type { };
+
+template <class _Stream, class _Tp>
+struct __is_istreamable<_Stream, _Tp, decltype(
+ _VSTD::declval<_Stream>() >> _VSTD::declval<_Tp>(), void()
+)> : true_type { };
+
+template <class _Stream, class _Tp, class = typename enable_if<
+ _And<is_base_of<ios_base, _Stream>,
+ __is_istreamable<_Stream&, _Tp&&>>::value
+>::type>
+_LIBCPP_INLINE_VISIBILITY
+_Stream&& operator>>(_Stream&& __is, _Tp&& __x)
{
__is >> _VSTD::forward<_Tp>(__x);
- return __is;
+ return _VSTD::move(__is);
}
#endif // _LIBCPP_CXX03_LANG
diff --git a/libcxx/include/ostream b/libcxx/include/ostream
index 697732d54e6d..809f601c7333 100644
--- a/libcxx/include/ostream
+++ b/libcxx/include/ostream
@@ -126,9 +126,8 @@ template <class charT, class traits>
basic_ostream<charT,traits>& flush(basic_ostream<charT,traits>& os);
// rvalue stream insertion
-template <class charT, class traits, class T>
- basic_ostream<charT, traits>&
- operator<<(basic_ostream<charT, traits>&& os, const T& x);
+template <class Stream, class T>
+ Stream&& operator<<(Stream&& os, const T& x);
} // std
@@ -1028,15 +1027,20 @@ flush(basic_ostream<_CharT, _Traits>& __os)
#ifndef _LIBCPP_CXX03_LANG
+template <class _Stream, class _Tp, class = void>
+struct __is_ostreamable : false_type { };
+
template <class _Stream, class _Tp>
-inline _LIBCPP_INLINE_VISIBILITY
-typename enable_if
-<
- !is_lvalue_reference<_Stream>::value &&
- is_base_of<ios_base, _Stream>::value,
- _Stream&&
->::type
-operator<<(_Stream&& __os, const _Tp& __x)
+struct __is_ostreamable<_Stream, _Tp, decltype(
+ _VSTD::declval<_Stream>() << _VSTD::declval<_Tp>(), void()
+)> : true_type { };
+
+template <class _Stream, class _Tp, class = typename enable_if<
+ _And<is_base_of<ios_base, _Stream>,
+ __is_ostreamable<_Stream&, const _Tp&>>::value
+>::type>
+_LIBCPP_INLINE_VISIBILITY
+_Stream&& operator<<(_Stream&& __os, const _Tp& __x)
{
__os << __x;
return _VSTD::move(__os);
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/not_istreamable.verify.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/not_istreamable.verify.cpp
new file mode 100644
index 000000000000..1a03ed69b140
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/not_istreamable.verify.cpp
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// Make sure the rvalue overload of operator>> isn't part of the overload set
+// when the type is not input streamable from a lvalue stream.
+
+#include <istream>
+#include <utility>
+
+struct Foo { };
+
+using X = decltype(std::declval<std::istream>() >> std::declval<Foo&>()); // expected-error {{invalid operands to binary expression}}
+using Y = decltype(std::declval<std::istream>() >> std::declval<Foo>()); // expected-error {{invalid operands to binary expression}}
diff --git a/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/rvalue.pass.cpp b/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/rvalue.pass.cpp
index df65aed76dfd..70ada3a9239f 100644
--- a/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/rvalue.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/input.streams/istream.rvalue/rvalue.pass.cpp
@@ -10,9 +10,8 @@
// <istream>
-// template <class charT, class traits, class T>
-// basic_istream<charT, traits>&
-// operator>>(basic_istream<charT, traits>&& is, T&& x);
+// template <class Stream, class T>
+// Stream&& operator>>(Stream&& is, T&& x);
#include <istream>
#include <sstream>
@@ -44,32 +43,44 @@ struct testbuf
CharT* egptr() const {return base::egptr();}
};
+struct Int {
+ int value;
+ template <class CharT>
+ friend void operator>>(std::basic_istream<CharT>& is, Int& self) {
+ is >> self.value;
+ }
+};
-struct A{};
+struct A { };
bool called = false;
-void operator>>(std::istream&, A&&){ called = true; }
+void operator>>(std::istream&, A&&) { called = true; }
int main(int, char**)
{
{
testbuf<char> sb(" 123");
- int i = 0;
- std::istream(&sb) >> i;
- assert(i == 123);
+ Int i = {0};
+ std::istream is(&sb);
+ std::istream&& result = (std::move(is) >> i);
+ assert(&result == &is);
+ assert(i.value == 123);
}
{
testbuf<wchar_t> sb(L" 123");
- int i = 0;
- std::wistream(&sb) >> i;
- assert(i == 123);
+ Int i = {0};
+ std::wistream is(&sb);
+ std::wistream&& result = (std::move(is) >> i);
+ assert(&result == &is);
+ assert(i.value == 123);
}
- { // test perfect forwarding
+ {
+ // test perfect forwarding
assert(called == false);
std::istringstream ss;
- auto&& out = (std::move(ss) >> A{});
- assert(&out == &ss);
+ std::istringstream&& result = (std::move(ss) >> A{});
+ assert(&result == &ss);
assert(called);
}
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/not_ostreamable.verify.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/not_ostreamable.verify.cpp
new file mode 100644
index 000000000000..7ca36c562261
--- /dev/null
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/not_ostreamable.verify.cpp
@@ -0,0 +1,19 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03
+
+// Make sure the rvalue overload of operator<< isn't part of the overload set
+// when the type is not output streamable into a lvalue stream.
+
+#include <ostream>
+#include <utility>
+
+struct Foo { };
+
+using X = decltype(std::declval<std::ostream>() << std::declval<Foo const&>()); // expected-error {{invalid operands to binary expression}}
diff --git a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/CharT_pointer.pass.cpp b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/rvalue.pass.cpp
similarity index 71%
rename from libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/CharT_pointer.pass.cpp
rename to libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/rvalue.pass.cpp
index 87ab6bae3907..99e70c425169 100644
--- a/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/CharT_pointer.pass.cpp
+++ b/libcxx/test/std/input.output/iostream.format/output.streams/ostream.rvalue/rvalue.pass.cpp
@@ -10,12 +10,8 @@
// <ostream>
-// template <class charT, class traits = char_traits<charT> >
-// class basic_ostream;
-
-// template <class charT, class traits, class T>
-// basic_ostream<charT, traits>&
-// operator<<(basic_ostream<charT, traits>&& os, const T& x);
+// template <class Stream, class T>
+// Stream&& operator<<(Stream&& os, const T& x);
#include <ostream>
#include <cassert>
@@ -55,19 +51,32 @@ class testbuf
}
};
+struct Int {
+ int value;
+ template <class CharT>
+ friend void operator<<(std::basic_ostream<CharT>& os, Int const& self) {
+ os << self.value;
+ }
+};
int main(int, char**)
{
{
testbuf<char> sb;
- std::ostream(&sb) << "testing...";
- assert(sb.str() == "testing...");
+ std::ostream os(&sb);
+ Int const i = {123};
+ std::ostream&& result = (std::move(os) << i);
+ assert(&result == &os);
+ assert(sb.str() == "123");
}
{
testbuf<wchar_t> sb;
- std::wostream(&sb) << L"123";
+ std::wostream os(&sb);
+ Int const i = {123};
+ std::wostream&& result = (std::move(os) << i);
+ assert(&result == &os);
assert(sb.str() == L"123");
}
- return 0;
+ return 0;
}
diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html
index d1bf4744b495..25d9f24a001f 100644
--- a/libcxx/www/cxx2a_status.html
+++ b/libcxx/www/cxx2a_status.html
@@ -468,7 +468,7 @@ <h3>Library Working group Issues Status</h3>
<tr><td><a href="https://wg21.link/LWG3149">3149</a></td><td><tt>DefaultConstructible</tt> should require default initialization</td><td>Belfast</td><td></td></tr>
<tr><td></td><td></td><td></td><td></td></tr> -->
- <tr><td><a href="https://wg21.link/LWG1203">1203</a></td><td>More useful rvalue stream insertion</td><td>Prague</td><td></td></tr>
+ <tr><td><a href="https://wg21.link/LWG1203">1203</a></td><td>More useful rvalue stream insertion</td><td>Prague</td><td>12.0</td></tr>
<tr><td><a href="https://wg21.link/LWG2859">2859</a></td><td>Definition of <em>reachable</em> in [ptr.launder] misses pointer arithmetic from pointer-interconvertible object</td><td>Prague</td><td></td></tr>
<tr><td><a href="https://wg21.link/LWG3018">3018</a></td><td><tt>shared_ptr</tt> of function type</td><td>Prague</td><td></td></tr>
<tr><td><a href="https://wg21.link/LWG3050">3050</a></td><td>Conversion specification problem in <tt>chrono::duration</tt> constructor</td><td>Prague</td><td></td></tr>
More information about the libcxx-commits
mailing list