c++ - 为什么需要复制扣除候选作为单独的扣除指南?

标签 c++ templates c++17 template-argument-deduction

template <typename T> struct A {
    A(T);
    A(const A&);
};

int main()
{
    A x(42); // #1
    A y = x; // #2
}

据我了解,#1 的 T 将使用隐式演绎指南进行演绎 从第一个 ctor 生成。然后 x 将使用该ctor初始化。

不过,对于 #2,T 将使用复制推导候选(据我了解,这是推导指南的一个特定情况)推导(然后是 y 将使用第二个 ctor 进行初始化)。

为什么不能使用从 copy-ctor 生成的(隐式)推导指南来推导 #2 的 T

我想我只是不明白复制扣除候选人的一般用途。

最佳答案

添加复制扣除的措辞的初稿是P0620R0 ,其中提到

This paper is intended to resolve

  • The direction on wrapping vs. copying from EWG on Monday in Kona

关于那次 session 的一些笔记可在 https://botondballo.wordpress.com/2017/03/27/trip-report-c-standards-meeting-in-kona-february-2017/ :

Copying vs. wrapping behaviour. Suppose a is a variable of type tuple<int, int>, and we write tuple b{a};. Should the type of b be tuple<int, int> (the "copying" behaviour), or tuple<tuple<int, int>> (the "wrapping" behaviour)? This question arises for any wrapper-like type (such as pair, tuple, or optional) which has both a copy constructor and a constructor that takes an object of the type being wrapped. EWG felt copying was the best default. There was some talk of making the behaviour dependent on the syntax of the initialization (e.g. the { } syntax should always wrap) but EWG felt introducing new inconsistencies between the behaviours of different initialization syntaxes would do more harm than good.

@kiloalphaindia explained this in a comment :

If #2 would use A::A(T) we would end up with y beeing A<A<int>>. [...]

这是对的。 A<A<int>>::A(A<int>)构造函数的参数类型完全匹配。另一方面,你也是对的 A<int>::A(const A<int> &)在这种情况下会被首选。

但请考虑这个替代方案,其中函数等价物表明 A<A<int>>如果不是复制扣除候选人,那将是首选:

template <typename T>
struct A {
    A(T &&);
    A(const A<T> &);
};

template <typename T> auto f(T &&) -> A<T>;
template <typename T> auto f(const A<T> &) -> A<T>;

int main() {
  A x1(42);                   // A<int>
  A y1 = std::move(x1);       // A<int>

  auto x2 = f(42);            // A<int>
  auto y2 = f(std::move(x2)); // A<A<int>>
}

关于c++ - 为什么需要复制扣除候选作为单独的扣除指南?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50292874/

相关文章:

C++ 模板类中函数指针的问题

c++ - 检查两个函数或成员函数指针的签名是否相等

c++ - 使用初始化列表初始化类中的 std::ofstream

c++ - 模板参数默认为后一个

c++ - 为什么不能为显式模板特化指定默认参数?

c++ - 如何防止构造函数中的 bool 到 int 转换?

c++ - 将方法作为回调从一个类传递到另一个类

c++ - 在多线程 C++11 程序中未处理异常时会发生什么?

c++ - header 中的模板不允许我使用我的类(class)?

c++ - 具有公共(public)基础的派生类的模板特化