[committed] libstdc++: Implement LWG 1203 for rvalue iostreams
Jonathan Wakely
jwakely@redhat.com
Fri May 7 22:49:09 GMT 2021
On 06/05/21 18:28 +0100, Jonathan Wakely wrote:
>On 06/05/21 18:09 +0100, Jonathan Wakely wrote:
>>On 06/05/21 17:55 +0200, Stephan Bergmann wrote:
>>>On 30/04/2021 15:48, Jonathan Wakely via Libstdc++ wrote:
>>>>This implements the resolution of LWG 1203 so that the constraints for
>>>>rvalue stream insertion/extraction are simpler, and the return type is
>>>>the original rvalue stream type not its base class.
>>>>
>>>>Signed-off-by: Jonathan Wakely <jwakely@redhat.com>
>>>>
>>>>libstdc++-v3/ChangeLog:
>>>>
>>>> * include/std/istream (operator>>(Istream&&, x&)): Simplify, as
>>>> per LWG 1203.
>>>> * include/std/ostream (operator<<(Ostream&&, const x&)):
>>>> Likewise.
>>>> * testsuite/27_io/basic_istream/extractors_character/char/lwg2499_neg.cc:
>>>> Adjust dg-error pattern.
>>>> * testsuite/27_io/basic_istream/extractors_character/wchar_t/lwg2499_neg.cc:
>>>> Likewise.
>>>> * testsuite/27_io/basic_istream/extractors_other/char/4.cc: Define
>>>> is_extractable trait to replace std::__is_extractable. Make it
>>>> work with rvalue streams as well as lvalues, to replace f() and
>>>> g() helper functions.
>>>> * testsuite/27_io/basic_istream/extractors_other/wchar_t/4.cc:
>>>> Likewise.
>>>> * testsuite/27_io/basic_ostream/inserters_other/char/6.cc:
>>>> Define is_insertable trait to replace std::__is_insertable. Make
>>>> it work with rvalue streams as well as lvalues, to replace f()
>>>> and g() helper functions.
>>>> * testsuite/27_io/basic_ostream/inserters_other/wchar_t/6.cc:
>>>> Likewise.
>>>> * testsuite/27_io/filesystem/path/io/dr2989.cc: Prune additional
>>>> errors from new constraints.
>>>> * testsuite/27_io/rvalue_streams-2.cc: Remove PR 80675 checks,
>>>> which are no longer expected to compile.
>>>> * testsuite/27_io/rvalue_streams.cc: Adjust existing test.
>>>> Verify LWG 1203 changes.
>>>>
>>>>Tested powerpc64le-linux. Committed to trunk.
>>>
>>>FWIW, it looks like this is causing issues for Clang (at least
>>>Clang 11 and recent Clang 13 trunk):
>>>
>>>>$ cat test.cc
>>>>#include <ostream>
>>>>int i = 1 << std::ios::erase_event;
>>>
>>>(i.e., using and enum in namespace std),
>>>
>>>>$ clang++ --gcc-toolchain=~/gcc/trunk/inst -fsyntax-only test.cc
>>>>In file included from test.cc:1:
>>>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:727:33: error: cannot initialize a parameter of type 'std::ios_base *' with an rvalue of type 'int *'
>>>> __rval_streamable(ios_base* = (_Tp*)nullptr);
>>>> ^ ~~~~~~~~~~~~~
>>>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:733:25: note: in instantiation of default function argument expression for '__rval_streamable<int, void>' required here
>>>> typename = decltype(std::__rval_streamable<_Os>()
>>>> ^
>>>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:748:12: note: in instantiation of default argument for '__rvalue_stream_insertion_t<int, std::ios_base::event>' required here
>>>> inline __rvalue_stream_insertion_t<_Ostream, _Tp>
>>>> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>>>test.cc:2:11: note: while substituting deduced template arguments into function template 'operator<<' [with _Ostream = int, _Tp = std::ios_base::event]
>>>>int i = 1 << std::ios::erase_event;
>>>> ^
>>>>~/gcc/trunk/inst/lib/gcc/x86_64-pc-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:727:33: note: passing argument to parameter here
>>>> __rval_streamable(ios_base* = (_Tp*)nullptr);
>>>> ^
>>>>1 error generated.
>>
>>It looks like the failed conversion with the default argument is not
>>in the immediate context, so is an error not a substitution failure.
>>Clang is probably right, so I'll change it.
>>
>>The reason I did it that way was to save instantiating
>>std::is_convertible but also because it seemed like an easy way to
>>avoid confusing diagnostics that say:
>>
>>error: forming pointer to reference type 'std::basic_ostream<char>&'
>>
>>for overload resolution failures for operator<< (because those
>>diagnostics are already hundreds of lines long and confusing enough
>>already).
>>
>>This seems to work:
>>
>>--- a/libstdc++-v3/include/std/ostream
>>+++ b/libstdc++-v3/include/std/ostream
>>@@ -722,9 +722,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> __rval_streamable();
>>#else
>> template<typename _Tp,
>>- typename = _Require<__not_<__is_one_of<_Tp, _Tp&, ios_base>>>>
>>+ typename = _Require<__not_<is_same<_Tp, ios_base>>,
>>+ is_convertible<_Tp*, ios_base*>>>
>> _Tp&
>>- __rval_streamable(ios_base* = (_Tp*)nullptr);
>>+ __rval_streamable();
>>#endif
>>
>> // SFINAE helper to check constraints for operator<<(Ostream&&, const T&).
>>
>>
>>I'll finish testing that.
>
>Actually, if the function parameter can't be used for the convertible
>check then there's no benefit to that function at all. It's simpler to
>just put all the constraints directly on the alias template that also
>checks the operator<< expression:
>
> // SFINAE helper to check constraints for operator<<(Ostream&&, const T&).
> // If the constraints are satisfied, it is an alias for Ostream&&.
>#if __cpp_lib_concepts
> // Use concepts if possible because they're cheaper to evaluate.
> template<typename _Os, typename _Tp>
> requires (!is_same_v<_Os, ios_base>)
> && (!is_lvalue_reference_v<_Os>)
> && requires (_Os* __os, ios_base* __b, const _Tp& __t) {
> __b = __os;
> *__os << __t;
> }
>#else
> template<typename _Os, typename _Tp,
> typename = _Require<__not_<is_same<_Os, ios_base>>,
> is_convertible<_Os*, ios_base*>>,
> typename
> = decltype(std::declval<_Os&>() << std::declval<const _Tp&>())>
>#endif
> using __rvalue_stream_insertion_t = _Os&&;
Here's what I've pushed to trunk, and will push to gcc-11 after
testing it on the branch.
Tested x86_64-linux and powerpc64le-linux.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 8957 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20210507/31e923c5/attachment.bin>
More information about the Libstdc++
mailing list