https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125605

songb432 at gmail dot com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |---

--- Comment #6 from songb432 at gmail dot com ---
(In reply to Patrick Palka from comment #5)
> > There's a ridiculous point: if I change `template <class> concept X = true` 
> > into `template <class T> concept X = requires { typename 
> > type_identity_t<T>; };` or something else concerning eventually a truly 
> > type dependent constraint (the evaluated result is truly type dependent), 
> > then everything (including that `has_usable_pointer` example) works 
> > perfectly.
> 
> GCC is behaving correctly here, even though it's somewhat surprising at
> first. The main thing is that the parameter mapping of an atomic constraint
> involves only the template parameters that are _used_ in the atomic
> constraint expression. The concept C = true doesn't use any of its template
> parameters, so during normalization we effectively ignore its corresponding
> template arguments.
> 
> That's why in https://eel.is/c++draft/temp.constr#normal-example-1 the
> concept A is defined as
> 
>   template<typename T> concept A = T::value || true; // uses T
> 
> If it was defined as just
> 
>   template<typename T> concept A = true;
> 
> then normalization of C wouldn't be erroneous since the parameter mapping
> would be empty and we wouldn't form the invalid type V&* anywhere.
> 
> Doing `= requires { typename T; }` instead of `= true` is the recommended
> approach if you want your examples to work in the way you expect.



I suppose you're right there. But let's see `Example3`:
```
namespace Example3 { // see also
https://eel.is/c++draft/temp.constr#decl-example-2
template <class T> concept C = true;
template <class T> struct A {
  template <class U> U f(U) requires C<typename T::type>;   // #1
  template <class U> U f(U) requires C<T>;                  // #2
};
using U = decltype(A<int>{}.f(2));
} // namespace Example3
```
It doesn't compile because the compiler thinks `call of overloaded 'f(int)' is
ambiguous`.
I think it's a bug. Because the original example in standard draft also has
```
template <> template <class U>
U A<int>::f(U u) requires C<int> { return u; }              // OK, specializes
#2
```
And this does compile, while `A<int>{}.f(2)` does not.

Reply via email to