Description
The wording of [temp.func.order]/3
To produce the transformed template, for each type, constant, type template, variable template, or concept template parameter (including template parameter packs ([temp.variadic]) thereof) synthesize a unique type, value, class template, variable template, or concept, respectively, and substitute it for each occurrence of that parameter in the function type of the template.
is vague and leaves the precise nature of the transformed function type to be easily misunderstood. Consider, for example:
template <typename T>
void f(T, typename std::type_identity_t<T>);
Intuitively, one might expect the transformed function type to be
void (A, A)
where A
is some unique invented type. However, the intention seems to be that the transformed function type in this case becomes
void (A, B)
where A
and B
are distinct invented types. i.e., the transformation performs substitution only, type-specifiers that would require template instantiation to resolve are considered to give rise to distinct types of their own.
We would suggest to add a note of this fact and, ideally, some examples to illustrate this key issue. e.g.:
#include <type_traits>
template <typename T> void f(T, T); // #1
template <typename T> void f(T, std::type_identity_t<T>); // #2, less specialized than #1
template <typename T> using identity_t = T;
template <typename T> void f(T, identity_t<T>); // redeclaration of #1
Big thanks to @michael-kenzel for the explanation and the example.