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.