[committed] libstdc++: Implement string_view range constructor for C++23

Jonathan Wakely jwakely@redhat.com
Tue Apr 27 16:56:32 GMT 2021


On 27/04/21 17:31 +0100, Jonathan Wakely wrote:
>On 27/04/21 16:34 +0200, Stephan Bergmann wrote:
>>On 23/03/2021 00:16, Jonathan Wakely via Gcc-patches wrote:
>>>This implements the new string_view constructor proposed by P1989R2.
>>>This hasn't been voted into the C++23 draft yet, but it's been reviewed
>>>by LWG and is expected to be approved at the next WG21 meeting.
>>>
>>>libstdc++-v3/ChangeLog:
>>>
>>>	* include/std/string_view (basic_string_view(Range&&)): Define new
>>>	constructor and deduction guide.
>>>	* testsuite/21_strings/basic_string_view/cons/char/range_c++20.cc: New test.
>>>	* testsuite/21_strings/basic_string_view/cons/wchar_t/range_c++20.cc: New test.
>>>
>>>Tested powerpc64le-linux. Committed to trunk.
>>>
>>>(I wrote "C++20" in the commit log summary but it's a C++23 feature,
>>>which is why I'm confortable pushing it now in stage 4.)
>>
>>I observe that with this change, recent Clang 13 trunk with 
>>-std=c++2b starts to fail on Boost's boost/spirit/include/qi.hpp (at 
>>least both Boost 1.73 and 1.75).  I unfortunately wasn't able to 
>>reduce this to a reasonably small testcase, and have no idea whether 
>>its a Clang, libstdc++, or a even Boost issue.
>
>Thanks for the heads up.
>
>I think this is a recursive constraint problem, where the new
>constructor participates in overload resolution so we try to satisfy
>its constraints, but those constraints depend on the thing that caused
>us to attempt overload resolution for that constructor.
>
>But it's not obvious from the errors what triggers that.

It's trying to see if a spirit::info is convertible to std::string,
which considers this constructor:

basic_string(const T&, const Alloc& = Alloc());

That is constructor (10) at:
https://en.cppreference.com/w/cpp/string/basic_string/basic_string
that is constrained by:

std::is_convertible_v<const T&, std::basic_string_view<CharT, Traits>>
is true and std::is_convertible_v<const T&, const CharT*> is false.

Where T is pair<spirit::info, spirit::info>.

To see if the constructor is viable, we check if pair<spirit::info, spirit::info>
can be converted to std::string_view, which considers the new constructor,
which needs to check if that pair is a range. Somewhere deep in the
range requirements we require that is_move_assignable<pair<>> is
true, so we can do DECAY-COPY(begin(r)), which is ill-formed because the
spirit::info type is incomplete, because we're still in its class definition.

We've seen problems like this before. It's nasty.




More information about the Libstdc++ mailing list