Title
Forwarding references and deduction guides
Status
open
Section
17.9.2.4 [temp.deduct.partial]
Submitter
Barry Revzin

Created on 2017-06-03.00:00:00, last changed 2017-06-03.00:00:00.

Messages

Date: 2017-06-03.00:00:00

Consider an example like:

  template<typenameT>
  struct A {
    A(const T&);        // #1
    A(T&&);             // #2
  };

  template<typenameU>
  A(U&&)->A<double>;    // #3

  int main(){
    int i =0;
    const int ci =0;

    A a1(0);
    A a2(i);
    A a3(ci);
  }

This example is covered by 17.9.2.4 [temp.deduct.partial] paragraph 9:

If, for a given type, deduction succeeds in both directions (i.e., the types are identical after the transformations above) and both P and A were reference types (before being replaced with the type referred to above):

  • if the type from the argument template was an lvalue reference and the type from the parameter template was not, the parameter type is not considered to be at least as specialized as the argument type; otherwise,

  • if the type from the argument template is more cv-qualified than the type from the parameter template (as described above), the parameter type is not considered to be at least as specialized as the argument type.

For a2(i), the deduction guide is the best match, so this is an A<double>.

For a3(ci), the first bullet applies, which prefers #1 to #3 since #1 comes from an lvalue reference and #3 does not, resulting in an A<int>.

For a1(0), the case is not covered by partial ordering, so 16.3.3 [over.match.best] bullet 1.10 applies and prefers #3 to #2, which is again an A<double>.

It seems inconsistent to prefer #1 to #3 (T const & to U&&), but to prefer #3 to #2 (U&& to T&&). Should the rules be expanded to basically prefer any non-forwarding-reference to a forwarding reference?

History
Date User Action Args
2017-06-03 00:00:00admincreate