Mixing immediate and non-immediate contexts in deduction failure
13.10.3 [temp.deduct]
Daniel Krügler

Created on 2010-11-27.00:00:00 last changed 90 months ago


Date: 2012-10-15.00:00:00

[Moved to DR at the October, 2012 meeting.]

Date: 2012-02-15.00:00:00

Proposed resolution (February, 2012):

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. [Note: The equivalent substitution in exception specifications is done only when the function 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(...) { }

  void h() {
    f<int>(0); // OK, substituting return type causes deduction to fail
    g<int>(0); // error, substituting parameter type instantiates A<int>

end example]

Date: 2011-03-15.00:00:00

Notes from the March, 2011 meeting:

Some members expressed a desire to allow implementations latitude in whether examples like this should be deduction failure or a diagnosable error, just as the order of evaluation of arithmetic operands is largely unconstrained. Others felt that specifying something like a depth-first left-to-right traversal of the expression or declaration would be better. Another possibility suggested was to enforce ordering only at comma operators. No consensus was achieved.

CWG agreed that the arguments should be processed in left-to-right order. Some popular existing code (e.g., Boost) depends on this ordering.

Date: 2010-11-27.00:00:00

Consider the following example:

    template <int> struct X {
      typedef int type;
    template <class T> struct Y { };
    template <class T> struct Z {
      static int const value = Y<T>::value;

    template <class T> typename X<Y<T>::value + Z<T>::value>::type f(T);
    int f(...);

    int main() {
      sizeof f(0);

The problem here is that there is a combination of an invalid expression in the immediate context (Y<T>::value) and in the non-immediate context (within Z<T> when evaluating Z<T>::value). The Standard does not appear to state clearly whether this program is well-formed (because the error in the immediate context causes deduction failure) or ill-formed (because of the error in the non-immediate context).

Date User Action Args
2014-03-03 00:00:00adminsetstatus: drwp -> cd3
2013-05-03 00:00:00adminsetstatus: dr -> drwp
2012-11-03 00:00:00adminsetmessages: + msg4162
2012-11-03 00:00:00adminsetstatus: ready -> dr
2012-02-27 00:00:00adminsetmessages: + msg3738
2012-02-27 00:00:00adminsetstatus: drafting -> ready
2011-09-06 00:00:00adminsetstatus: open -> drafting
2011-04-10 00:00:00adminsetmessages: + msg3276
2010-11-27 00:00:00admincreate