使用扣除指南

时间:2017-06-03 17:05:46

标签: c++ templates language-lawyer c++17 template-deduction

gcc 8.0.0clang 5.0.0对此计划的行为持不同意见:

#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的行为对我没有意义 - 如果const T&重载优先于左值U&&的{​​{1}}重载,为什么不是&#39;对于右值const intT&&重载优先于U&&重载? clang对我来说更有意义(没有一个功能比另一个更专业,所以演绎指南获胜)。

谁对吗?

1 个答案:

答案 0 :(得分:7)

我们再次部分订购土地。合成的函数模板参数的类型是

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

预偏序转换strips away referenceness以及之后的top-level cv-qualification,在所有三种情况下都留下了裸露类型。由此可见,在所有三种情况下,推导都在两个方向上都成功。我们现在离开了[temp.deduct.partial]/9的决胜局:

  

如果对于给定类型,扣除在两个方向上都成功(即,   在上述转换之后,类型是相同的,并且P和A都是相同的   是引用类型(在被引用的类型替换之前)   上面):

     
      
  • 如果参数模板中的类型是左值   引用和参数模板中的类型不是,   参数类型不被认为至少与   参数类型;否则,
  •   
  • 如果参数模板中的类型   比参数模板中的类型更具cv限定(如   如上所述,参数类型至少不被认为是   与参数类型一样专门。
  •   

对于U&& vs T&&,这两条规则都不适用且没有排序。但是,对于U&& vs const T&,根据第一个项目符号,参数类型U&&不会被认为至少与参数类型const T&一样专业。

部分排序因此发现#2比#3更专业,但发现#1和#3无法区分。海湾合作委员会是正确的。

也就是说,这可能是部分订购规则的疏忽。类模板推导是我们第一次对cv-unqualified模板参数进行&#34; rvalue引用,该参数不是转发引用&#34;事情。以前,在双引用的情况下,转发引用总是会丢失到第二个项目符号的非转发右值引用(因为你获得非转发右值引用的唯一方法是,对于某些非空{cv T&& {1}})。