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

2024-12-19


606. Template argument deduction for rvalue references

Section: 13.10.3.2  [temp.deduct.call]     Status: CD1     Submitter: Peter Dimov     Date: 1 December 2006

[Voted into the WP at the September, 2008 meeting as part of paper N2757.]

There are a couple of minor problems with the rvalue reference wording in the WP. The non-normative note in 13.10.3.2 [temp.deduct.call] paragraph 3 says,

[Note: The effect of this rule for lvalue arguments and rvalue reference parameters is that deduction in such cases will fail unless the function parameter is of the form cv T&& (13.10.3.6 [temp.deduct.type]). —end note]

It turns out that this isn't correct. For example:

    template <class T> void g(basic_string<T> && );
    ...
    basic_string<char> s;
    g(s);    // Note says that it should fail, we want it to call
             // g<char>(basic_string<char>&&)

Additionally, consider this case:

    template <class T> void f(const T&&);
    ...
    int i;
    f(i);

If we deduce T as int& in this case then f(i) calls f<int&>(int&), which seems counterintuitive. We prefer that f<int>(const int&&) be called. Therefore, we would like the wording clarified that the A& deduction rule in 13.10.3.2 [temp.deduct.call] paragraph 3 applies only to the form T&& and not to cv T&& as the note currently implies.

These are minor tweaks to the rvalue reference wording and a fallout from issue 540. In particular, the major applications of move semantics and perfect forwarding are not impacted with respect to the original intentions of the rvalue reference work by these suggestions.

Suggested resolution:

Change 13.10.3.2 [temp.deduct.call] paragraph 3 as follows:

If P is an rvalue reference type 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 T is deduced as A&. [Example:

    template <typename T> int f(T&&);
    int i;
    int j = f(i); // calls f<int&>(i)
    template <typename T> int g(const T&&);
    int k;
    int n = g(k); // calls g<int>(k)

end example][Note: The effect of this rule for lvalue arguments and rvalue reference parameters is that deduction in such cases will fail unless the function parameter is of the form cv T&& (13.10.3.6 [temp.deduct.type]). —end note]

Proposed resolution (August, 2008):

Change 13.10.3.2 [temp.deduct.call] paragraph 3 as follows:

If P is an rvalue reference type 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. [Example:

    template <typename T> int f(T&&);
    int i;
    int j = f(i); // calls f<int&>(i)
    template <typename T> int g(const T&&);
    int k;
    int n = g(k); // calls g<int>(k)

end example][Note: The effect of this rule for lvalue arguments and rvalue reference parameters is that deduction in such cases will fail unless the function parameter is of the form cv T&& (13.10.3.6 [temp.deduct.type]). —end note]