[PATCH 3/3] libstdc++: Implement C++20 range adaptors

Stephan Bergmann sbergman@redhat.com
Tue Feb 18 07:31:00 GMT 2020


On 18/02/2020 02:20, Patrick Palka wrote:
> On Mon, 17 Feb 2020, Stephan Bergmann wrote:
>> On 04/02/2020 03:07, Patrick Palka wrote:
>>> This patch implements [range.adaptors].  It also includes the changes from
>>> P3280
>>> and P3278 and P3323, without which many standard examples won't work.
>>
>> I see that with this
>> <https://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;a=commit;h=cba9ef069e58eac00f30489d3ef21390caee6e45>
>> "libstdc++: Implement C++20 range adaptors", compiling <ranges> with recent
>> Clang trunk (which appears to mostly implement C++20 concepts now) in
>> -std=c++2a mode fails as below (besides also failing due to some "missing"
>> typenames, where Clang apparently doesn't yet implement P0634R3).  And I'm not
>> sure which of Clang vs. GCC is right here.
>>
>> The failure is
>>
>>> gcc/trunk/inst/include/c++/10.0.1/ranges:1512:47: error: ambiguous deduction
>>> for template arguments of '_RangeAdaptor'
>>>      inline constexpr __adaptor::_RangeAdaptor filter
>>>                                                ^
>>> gcc/trunk/inst/include/c++/10.0.1/ranges:1073:2: note: candidate function
>>> [with _Callable = std::ranges::views::(lambda at
>>> gcc/trunk/inst/include/c++/10.0.1/ranges:1513:9)]
>>>          _RangeAdaptor(const _Callable& = {})
>>>          ^
>>> gcc/trunk/inst/include/c++/10.0.1/ranges:1078:2: note: candidate function
>>> [with _Callable = std::ranges::views::(lambda at
>>> gcc/trunk/inst/include/c++/10.0.1/ranges:1513:9)]
>>>          _RangeAdaptor(_Callable __callable)
>>>          ^
>>
>> and a stripped-down reproducer is
>>
>>> template<typename T> struct S {
>>>    S(T const &) requires true;
>>>    S(T) requires false;
>>> };
>>> S s = 0;
>>
>> (Clang accepts this when the last line is replaced with
>>
>>> S<int> s = 0;
>>
>> and thus no class template argument deduction needs to be done.)
>>
>> I think what is relevant here is [over.match.class.deduct]/1 in the current
>> spec, which specifies a helper set of hypothetical function templates based on
>> a class' constructors for class template argument deduction.  It details the
>> function templates' template parameters, function parameters, and return
>> types, but does not mention requires-clauses.  From my superficial
>> understanding of concepts and class template argument deduction it would thus
>> look like the constructors' requires-clauses should indeed not be taken into
>> account here?
> 
> Thanks for letting me know about this issue.  That would be my
> interpretation of the spec, too.  Maybe someone else could shed light on
> this question?
> 
> The following patch simplifies _RangeAdaptor's constructors to no longer
> need to be constrained and should resolve the deduction ambiguity error
> reported by Clang?  Unfortunately the patch triggers an ICE in GCC,
> which I'll look into tomorrow.

Thanks, I can confirm that patch works fine with Clang.

Btw, the "missing" typenames for Clang I mentioned above would be fixed 
with the following patch.  I don't know whether you would want to do 
that, as technically the current C++20-only code is fine, but here it is 
anyway:

> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 970e904bddd..c487dd612c2 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -1326,7 +1326,7 @@ namespace views
>  	static constexpr auto
>  	_S_iter_cat()
>  	{
> -	  using _Cat = iterator_traits<iterator_t<_Vp>>::iterator_category;
> +	  using _Cat = typename iterator_traits<iterator_t<_Vp>>::iterator_category;
>  	  if constexpr (derived_from<_Cat, bidirectional_iterator_tag>)
>  	    return bidirectional_iterator_tag{};
>  	  else if constexpr (derived_from<_Cat, forward_iterator_tag>)
> @@ -1549,7 +1549,7 @@ namespace views
>  	  static constexpr auto
>  	  _S_iter_cat()
>  	  {
> -	    using _Cat = iterator_traits<iterator_t<_Base>>::iterator_category;
> +	    using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category;
>  	    if constexpr (derived_from<_Cat, contiguous_iterator_tag>)
>  	      return random_access_iterator_tag{};
>  	    else
> @@ -2294,9 +2294,9 @@ namespace views
>  	  _S_iter_cat()
>  	  {
>  	    using _OuterCat
> -	      = iterator_traits<iterator_t<_Base>>::iterator_category;
> +	      = typename iterator_traits<iterator_t<_Base>>::iterator_category;
>  	    using _InnerCat
> -	      = iterator_traits<iterator_t<range_reference_t<_Base>>>
> +	      = typename iterator_traits<iterator_t<range_reference_t<_Base>>>
>  		 ::iterator_category;
>  	    if constexpr (_S_ref_is_glvalue
>  			  && derived_from<_OuterCat, bidirectional_iterator_tag>
> @@ -2765,7 +2765,7 @@ namespace views
>  	  static constexpr auto
>  	  _S_iter_cat()
>  	  {
> -	    using _Cat = iterator_traits<iterator_t<_Base>>::iterator_category;
> +	    using _Cat = typename iterator_traits<iterator_t<_Base>>::iterator_category;
>  	    if constexpr (derived_from<_Cat, forward_iterator_tag>)
>  	      return forward_iterator_tag{};
>  	    else



More information about the Libstdc++ mailing list