This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 110b. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2023-01-15


873. Deducing rvalue references in declarative contexts

Section: 13.10.3.6  [temp.deduct.type]     Status: C++11     Submitter: John Spicer     Date: 16 April, 2009

[Voted into WP at August, 2010 meeting.]

13.10.3.2 [temp.deduct.call] paragraph 3 gives the deduction of rvalue references special treatment in the context of a function call:

If P is of the form T&&, where T is a template parameter, and the argument is an lvalue, the type A& is used in place of A for type deduction.

A similar provision is needed, but is not present, in declarative contexts. For example:

    template<typename T> void f(T&&);
    template<> void f(int&) { }    // #1
    template<> void f(int&&) { }   // #2
    void g(int i) {
        f(i);    // calls f<int&>(int&), i.e., #1
        f(0);    // calls f<int>(int&&), i.e., #2
    }

There need to be rules that deduce the template arguments for the specializations in the same way that the arguments are deduced in the calls.

Proposed resolution (February, 2010):

  1. Change 13.10.3.6 [temp.deduct.type] paragraph 10 as follows:

  2. Similarly, if P has a form that contains (T), then each parameter type Pi of the respective parameter-type-list of P is compared with the corresponding parameter type Ai of the corresponding parameter-type-list of A. If P and A are function types that originated from deduction when taking the address of a function template (13.10.3.3 [temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is an rvalue reference to a cv-unqualified template parameter and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T). [Note: As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be deduced as X&. —end note] [Example:

      template<typename T> void f(T&&);
      template<> void f(int&) { }      // #1
      template<> void f(int&&) { }     // #2
      void g(int i) {
        f(i);   // calls f<int&>(int&), i.e., #1
        f(0);   // calls f<int>(int&&), i.e., #2
      }
    

    end example]

    If the parameter-declaration corresponding to Pi is a function parameter pack...

  3. Add a new section under 13.10.3 [temp.deduct], either before or after 13.10.3.6 [temp.deduct.type], as follows:

  4. 14.8.2.x Deducing template arguments from a function declaration [temp.deduct.decl]

    In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers. Specifically, this is done for explicit instantiations (13.9.3 [temp.explicit]), explicit specializations (13.9.4 [temp.expl.spec]), and certain friend declarations (13.7.5 [temp.friend]). This is also done to determine whether a function template specialization matches a placement operator new (6.7.5.5.3 [basic.stc.dynamic.deallocation], 7.6.2.8 [expr.new]). In all these cases, P is the type of the function template being considered as a potential match and A is the function type from the declaration. The deduction is done as described in 13.10.3.6 [temp.deduct.type].

    If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered (13.7.7.3 [temp.func.order]), deduction fails and the declaration is ill-formed.

(Note that the resolution of issue 674 depends on this resolution.)