public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jonathan Wakely <jwakely@redhat.com>
To: Stephan Bergmann <sbergman@redhat.com>
Cc: libstdc++@gcc.gnu.org
Subject: Re: [committed] libstdc++: Implement LWG 1203 for rvalue iostreams
Date: Thu, 6 May 2021 18:28:20 +0100	[thread overview]
Message-ID: <20210506172820.GC3008@redhat.com> (raw)
In-Reply-To: <20210506170956.GB3008@redhat.com>

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&&;


  reply	other threads:[~2021-05-06 17:28 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-04-30 13:48 Jonathan Wakely
2021-05-06 15:55 ` Stephan Bergmann
2021-05-06 17:09   ` Jonathan Wakely
2021-05-06 17:28     ` Jonathan Wakely [this message]
2021-05-07 22:49       ` Jonathan Wakely

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210506172820.GC3008@redhat.com \
    --to=jwakely@redhat.com \
    --cc=libstdc++@gcc.gnu.org \
    --cc=sbergman@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).