Partial ordering of the forwarding link and normal job with output guides

gcc 8.0.0 and clang 5.0.0 do not agree with the behavior of this program:

#include <iostream> template <typename T> struct A { A(const T&) { std::cout << __PRETTY_FUNCTION__ << '\n'; } A(T&&) { std::cout << __PRETTY_FUNCTION__ << '\n'; } }; template <typename U> A(U&&) -> A<double>; int main() { int i = 0; const int ci = 0; A a1(0); // both say A<double> A a2(i); // both say A<double> A a3(ci); // gcc says A<int>, clang says A<double> } 

gcc behavior doesn't make sense to me - if overloading const T& preferable to overloading U&& for lvalue const int , why not overloading T&& , preferred for overloading U&& for rvalue int ? clang makes more sense to me (none of the functions is more specialized than the other, so the deduction guide wins).

Who is right?

+8
c ++ language-lawyer templates c ++ 17
source share
1 answer

We are again in partial order. Type of synthesized function template parameters:

 T&& // #1: not a forwarding reference const T& // #2 U&& // #3: a forwarding reference 

The transformation of the preliminary partial ordering removes the referentiality , and after that the cv-qualification of the upper level , leaving us naked in all three cases. It follows that in all three cases, deduction succeeds in both directions. Now we are left with [temp.deduct.partial] / 9 tiebreaker:

If for a given type the output succeeds in both directions (i.e. the types are identical after the conversions above), and both P and A were reference types (before being replaced by the type mentioned 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 at least as specialized as the argument type; otherwise,
  • if the type from the argument template is larger than CV than the type from the parameter template (as described above), the parameter type is not considered at least as specialized as the type of the argument.

For U&& vs T&& , no rule or ordering is applied. However, for U&& vs const T& the parameter type of U&& not considered to be at least as specialized as the argument type of const T& , in the first pool.

Thus, partial ordering finds No. 2 more specialized than # 3, but finds # 1 and # 3 indistinguishable. GCC is correct.

However, this may be oversight of the partial order rules. Calculation of the class template is the first time that we have the link "rvalue for the cv-unqualified template parameter, which is not a send reference." Previously, in cases with a double link, redirect links were always lost to rvalue non-forwarded links in the second pool (since the only way to get rvalue non-forwarded links is if you have cv T&& for some non-empty cv ).

+7
source share

All Articles