Title
Substitution failure and lexical order
Status
cd5
Section
13.10.3 [temp.deduct]
Submitter
Xiang Fan

Created on 2016-09-06.00:00:00 last changed 40 months ago

Messages

Date: 2018-04-11.00:00:00

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 in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered. If substitution into different declarations of the same function template would cause template instantiations to occur in a different order or not at all, the program is ill-formed; no diagnostic required. [Note: The equivalent substitution in exception specifications is done only when the noexcept-specifier is instantiated, at which point a program is ill-formed if the substitution results 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(...) { }

  void h x() {
    f<int>(0);    // OK, substituting return type causes deduction to fail
    g<int>(0);    // error, substituting parameter type instantiates A<int>
    h<int>(0);    // ill-formed, no diagnostic required
  }

end example]

Date: 2018-06-15.00:00:00

[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 the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to 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);
  }
History
Date User Action Args
2020-12-15 00:00:00adminsetstatus: ready -> cd5
2018-04-11 00:00:00adminsetmessages: + msg6181
2018-04-11 00:00:00adminsetstatus: drafting -> ready
2016-09-06 00:00:00admincreate