-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Full name of submitter (unless configured in github; will be published with the issue): Hubert Tong
Reference (section label): temp.constr.normal
Link to reflector thread (if any): N/A
Issue description
Consider:
template <auto> constexpr bool B = true;
template <unsigned X0> concept C = B<X0>;
template <unsigned short X1> concept C2 = C<X1>;
template <unsigned X> void f() requires C<X>; // #1
template <unsigned X> int f() requires C2<X> && true; // #2
void g() {
return f<65536>(); // should probably call #1
}
void h() {
f<0>(); // ambiguous?
}
When forming the normalized constraints, it is unclear how the type of X1
in the definition of C2
affects the parameter mapping. https://wg21.link/temp.constr.normal#1.4 does not seem to address this at all.
There is implementation divergence:
GCC and MSVC reject the call to f
from g
(resolving to #2
) and similarly resolves the call to f
from h
to #2
.
Clang and EDG accept the call to f
from g
(resolving to #1
) and rejects the call to f
from h
as ambiguous.
Online compiler link: https://godbolt.org/z/hEKaosbWe
Adopting the GCC/MSVC behaviour, which seems to ignore the type of X1
in the definition of C2
, seems objectively wrong: 65536u
is not a value that C2
accepts.
The Clang and EDG behaviour suggests that the parameter mapping for the B<X0>
atomic constraints are different between #1
and #2
. Presumably when substituting X
from #2
into the normalized constraint for C2
, some decoration was included.
Suggested resolution
Introducing some sort of "shadow constraint" that X
is a valid template argument for a template parameter declared as unsigned short
when normalizing the use of C2
from #2
would reject the call from g
but accept the call from h
as resolving to #2
. This seems to be a sensible result, but leaves none of the surveyed implementations unscathed.