[Voted into WP at August, 2010 meeting.]
Proposed resolution (February, 2010): Change 13.10.3.6 [temp.deduct.type] paragraph 10 as
follows: Similarly, if P has a form that contains
(T) , then each parameter type
P i of the respective
parameter-type-list of P is compared with the
corresponding parameter type A i 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
P i and A i
are parameters of the top-level parameter-type-list of
P and A , respectively, P i
is adjusted if it is an rvalue reference to
a cv-unqualified template parameter and
A i is an lvalue reference, in which case
the type of P i is
changed to be the template parameter type (i.e.,
T&& is changed to simply
T ). [Note: As a result, when
P i is T&& and
A i is X& , the adjusted
P i will be T , causing
T to be deduced as X& . —end
note] [Example:
—end example] If the parameter-declaration corresponding to
P i is a function parameter pack... Add a new section under 13.10.3 [temp.deduct], either before
or after 13.10.3.6 [temp.deduct.type], as follows: 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.8.6.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.)
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
}
13.10.3.2 [temp.deduct.call] paragraph 3 gives the deduction of
rvalue references special treatment in the context of a function call: A similar provision is needed, but is not present, in declarative
contexts. For example: 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.
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.
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
}