aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2021-05-06 19:14:42 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-05-07 23:45:52 +0100
commita87ceadf17b4a899f3e74e2da8b6b209461d2742 (patch)
treef8f0207607a553c7387377730fff224eeda5561c /libstdc++-v3/include
parent7c4c9fcc0de865876fb25fe75f4ed6e143bd48c0 (diff)
downloadgcc-a87ceadf17b4a899f3e74e2da8b6b209461d2742.zip
gcc-a87ceadf17b4a899f3e74e2da8b6b209461d2742.tar.gz
gcc-a87ceadf17b4a899f3e74e2da8b6b209461d2742.tar.bz2
libstdc++: Fix constraints for rvalue stream insertion/extraction
The __rval_streamable() function was an attempt to test for convertibility cheaply and without confusing diagnostics. It doesn't work with Clang though, and is probably ill-formed. Replace that helper function with a check for derivation from ios_base, and use that in the alias templates __rvalue_stream_insertion_t and __rvalue_stream_extraction_t. Use concepts for the constraints when available. libstdc++-v3/ChangeLog: * include/std/istream (__rvalue_stream_extraction_t): Replace use of __rval_streamable. * include/std/ostream (__rvalue_stream_insertion_t): Likewise. (__rval_streamable): Remove. (_Require_derived_from_ios_base, __derived_from_ios_base): New helper for checking constraints. * testsuite/27_io/basic_istream/extractors_other/char/4.cc: Fix reference to the wrong subclause of the standard. * testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/char/6.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc: Likewise. * testsuite/27_io/basic_ostream/inserters_other/char/99692.cc: New test. * testsuite/27_io/filesystem/path/io/dr2989.cc: Adjust pruned errors.
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/std/istream13
-rw-r--r--libstdc++-v3/include/std/ostream36
2 files changed, 26 insertions, 23 deletions
diff --git a/libstdc++-v3/include/std/istream b/libstdc++-v3/include/std/istream
index ea34cce..5ad60db 100644
--- a/libstdc++-v3/include/std/istream
+++ b/libstdc++-v3/include/std/istream
@@ -958,12 +958,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 2328. Rvalue stream extraction should use perfect forwarding
// 1203. More useful rvalue stream insertion
- // SFINAE helper to check constraints for operator>>(Istream&&, T&&).
- // If the constraints are satisfied, it is an alias for Istream&&.
+#if __cpp_lib_concepts
+ template<typename _Is, typename _Tp>
+ requires __derived_from_ios_base<_Is>
+ && requires (_Is& __is, _Tp&& __t) { __is >> std::forward<_Tp>(__t); }
+ using __rvalue_stream_extraction_t = _Is&&;
+#else
template<typename _Is, typename _Tp,
- typename = decltype(std::__rval_streamable<_Is>()
- >> std::declval<_Tp>())>
+ typename = _Require_derived_from_ios_base<_Is>,
+ typename = decltype(std::declval<_Is&>() >> std::declval<_Tp>())>
using __rvalue_stream_extraction_t = _Is&&;
+#endif
/**
* @brief Generic extractor for rvalue stream
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index fdd2a87..9816973 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -708,31 +708,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 1203. More useful rvalue stream insertion
- // SFINAE helper to check constraints for operator<<(Ostream&&, const T&).
- // If Ostream is publicly and unambiguously derived from ios_base, then
- // __rval_streamable<Ostream>() is equivalent to declval<Ostream&>().
- // Otherwise, it results in a substitution failure. Specifically, it will
- // fail if Ostream is an lvalue reference or the same type as ios_base.
- // Use concepts if possible because they're cheaper to evaluate.
#if __cpp_lib_concepts
+ // Use concepts if possible because they're cheaper to evaluate.
template<typename _Tp>
- requires (!is_same_v<_Tp, ios_base>)
- && requires (_Tp* __t, ios_base* __b) { __b = __t; }
- _Tp&
- __rval_streamable();
+ concept __derived_from_ios_base = is_class_v<_Tp>
+ && (!is_same_v<_Tp, ios_base>)
+ && requires (_Tp* __t, ios_base* __b) { __b = __t; };
+
+ template<typename _Os, typename _Tp>
+ requires __derived_from_ios_base<_Os>
+ && requires (_Os& __os, const _Tp& __t) { __os << __t; }
+ using __rvalue_stream_insertion_t = _Os&&;
#else
- template<typename _Tp,
- typename = _Require<__not_<__is_one_of<_Tp, _Tp&, ios_base>>>>
- _Tp&
- __rval_streamable(ios_base* = (_Tp*)nullptr);
-#endif
+ template<typename _Tp>
+ using _Require_derived_from_ios_base
+ = _Require<is_class<_Tp>, __not_<is_same<_Tp, ios_base>>,
+ is_convertible<typename add_pointer<_Tp>::type, ios_base*>>;
- // SFINAE helper to check constraints for operator<<(Ostream&&, const T&).
- // If the constraints are satisfied, it is an alias for Ostream&&.
template<typename _Os, typename _Tp,
- typename = decltype(std::__rval_streamable<_Os>()
- << std::declval<const _Tp&>())>
+ typename = _Require_derived_from_ios_base<_Os>,
+ typename
+ = decltype(std::declval<_Os&>() << std::declval<const _Tp&>())>
using __rvalue_stream_insertion_t = _Os&&;
+#endif
/**
* @brief Generic inserter for rvalue stream