为什么拥有复制构​​造函数会导致此代码中断?

Why does having a copy constructor cause this code to break?

所以我有这个代码:

template<class T>
struct IntegerType
{
    T value;

    //Next line causes errors
    //constexpr IntegerType(IntegerType& value) : value(value.value) { }
    constexpr IntegerType(T value) : value(value) { }
};
template<class int_t>
class FullMult{
    int_t value;
    int_t carry;
    public:

    constexpr FullMult() : value(0), carry(0) { }
    constexpr FullMult(const int_t& value, const int_t& carry) : value(value), carry(carry) { }

};

int main()
{
    FullMult<IntegerType<unsigned int> > thing 
        = FullMult<IntegerType<unsigned int> >(
            IntegerType<unsigned int>(12),IntegerType<unsigned int>(12));
}

但是当我尝试通过取消注释行 constexpr IntegerType(IntegerType& value) : value(value.value) { } 来向类型 IntegerType 添加复制构造函数时,代码中断并告诉我我正在尝试使用 FullMult类型:

use of deleted function 'FullMult<IntegerType<unsigned int> >::FullMult(FullMult<IntegerType<unsigned int> >&&)'

这是给我错误的代码:

template<class T>
struct IntegerType
{
    T value;

    //Next line causes errors
    constexpr IntegerType(IntegerType& value) : value(value.value) { }
    constexpr IntegerType(T value) : value(value) { }
};
template<class int_t>
class FullMult{
    int_t value;
    int_t carry;
    public:

    constexpr FullMult() : value(0), carry(0) { }
    constexpr FullMult(const int_t& value, const int_t& carry) : value(value), carry(carry) { }

};

int main()
{
    FullMult<IntegerType<unsigned int> > thing 
        = FullMult<IntegerType<unsigned int> >(
            IntegerType<unsigned int>(12),IntegerType<unsigned int>(12));
}

这是怎么回事?

在线有一个问题:

constexpr FullMult(const int_t& value, const int_t& carry) : value(value), carry(carry)

您使用 const int_t 类型的参数初始化 class 成员 int_t value;。但是没有匹配的构造函数。 IntegerType copy-constructor 接受 non-const 引用并且不能绑定到 const int_t.

但是,即使您独立修复此行,还有第二个问题,即出现在您的错误消息中的问题。代码(为清楚起见缩写):

F thing = F(...bla...);

调用 F 的 move-constructor。或者至少,它会执行 copy/move 可访问性检查,即使该操作被省略也是如此。但是如错误消息所示,F(F&&) 被删除了。这是因为默认定义为:

F(F&& other): value(std::move(other.value)), carry(std::move(other.carry)) {}

但是 IntegerType 没有匹配的构造函数——采用 non-const 左值引用的 copy-constructor 没有绑定到 xvalue std::move(other.value).


这两个问题都可以通过使 IntegerType 复制构造函数接受 const 引用来解决。

或者,除了 copy-constructor 之外,还可以通过给 IntegerType 一个 move-constructor 来解决第二个问题。 (但第一个问题仍然存在)。