This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 119a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.
2025-12-20
[Accepted as a DR at the June, 2018 (Rapperswil) meeting.]
According to 13.10.3 [temp.deduct] paragraph 7,
The substitution occurs in all types and expressions that are used in thefunction type and in template parameter declarations. The expressionsinclude not only constant expressions such as those that appear in arraybounds or as nontype template arguments but also general expressions (i.e.,non-constant expressions) insidesizeof,decltype, andother contexts that allow non-constant expressions. The substitutionproceeds in lexical order and stops when a condition that causes deductionto fail is encountered.
However, the same type can be represented in different lexical orders.For example, there is implementation variance on the following example,presumably because of preferring different declarations:
template <class T> struct A { using X = typename T::X; }; template <class T> typename T::X f(typename A<T>::X); template <class T> auto f(typename A<T>::X) -> typename T::X; template <class T> void f(...) { } void h() { f<int>(0); }Proposed resolution, March, 2018:
Change 13.10.3 [temp.deduct] paragraph 7 as follows:
The substitution occurs in all types and expressions that are used inthe function type and in template parameter declarations. The expressionsinclude not only constant expressions such as those that appear in arraybounds or as nontype template arguments but also general expressions (i.e.,non-constant expressions) inside sizeof, decltype, and other contexts thatallow non-constant expressions. The substitution proceeds in lexical orderand stops when a condition that causes deduction to fail isencountered.If substitution into different declarations of the samefunction template would cause template instantiations to occur in adifferent order or not at all, the program is ill-formed; no diagnosticrequired. [Note: The equivalent substitution in exceptionspecifications is done only when thenoexcept-specifier isinstantiated, at which point a program is ill-formed if the substitutionresults in an invalid type or expression. —end note][Example:
template <class T> struct A { using X = typename T::X; }; template <class T> typename T::X f(typename A<T>::X); template <class T> void f(...) { } template <class T> auto g(typename A<T>::X) -> typename T::X; template <class T> void g(...) { } template <class T> typename T::X h(typename A<T>::X); template <class T> auto h(typename A<T>::X) -> typename T::X; // redeclaration template <class T> void h(...) { } voidhx() { f<int>(0); // OK, substituting return type causes deduction to fail g<int>(0); // error, substituting parameter type instantiatesA<int> h<int>(0); // ill-formed, no diagnostic required }—end example]