The latest standard draft N4910 has this example in [temp.over.link] regarding functional equivalence:
template<int I> concept C = true;
template<typename T> struct A {
void f() requires C<42>; // #1
void f() requires true; // OK, different functions
};
My understanding is that this is ok, since C<42>
and true
are unevaluated operands. Therefore according to [temp.over.link]/5 when considering whether the constraints are functionally equivalent, not the result of the expressions, but what operations are performed on which entity and in what order, is deciding functional equivalency of the constraints.
However if the constraints were functionally equivalent, then because they are not equivalent, by [temp.over.link]/7 the program would be ill-formed, no diagnostic required, as declaring the same member twice would make the program ill-formed.
On the other hand
template<typename>
requires C<42>
void g() {};
template<typename>
requires true
void g() {};
seems to be ill-formed, no diagnostic required, because [temp.over.link]/6 says that template heads are functionally equivalent if they accept and satisfy the same template arguments.
Am I misunderstanding the example and referenced standard wording or is there really such a difference? If so, why?
template<class> int f()
andtemplate<std::same_as<int>> int f()
, for example, can both be instantiated with<int>
, so the constraints need to be mangled to differentiate the two. – Mcgrath