无法在C ++ 17中构造一个包含const int和不可复制(但可移动)对象的对

时间:2018-11-07 21:01:23

标签: c++ c++17

我有一个类,我将其称为NonCopyable,该类无法复制,但可以移动(构造移动和分配移动)。我正在尝试构造一个std::pair<const int, NonCopyable>,但是下面的行将无法编译。

std::pair<const int, NonCopyable>(1, NonCopyable());

我收到的错误是:

no matching function for call to 'std::pair<const int, NonCopyable>::pair(int, NonCopyable)'

为什么该行无法编译?由于NonCopyable是可构造/可移动的,所以我希望它使用构造函数template<class U1, class U2> constexpr pair(U1&& x, U2&& y)

编辑:

所以我遗漏了一些我认为不相关的信息,但实际上是并且非常重要。

我有一个类ContainsNC,它包含一个不可复制的类NonCopyable。我正在尝试构造一个std::pair<const int, ContainsNC>,但是下面的代码无法编译。

#include <utility>
#include <thread>
#include <iostream>
struct NonCopyable {
    NonCopyable() = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable(NonCopyable&&) = default;
    NonCopyable& operator=(const NonCopyable&) = delete;
    NonCopyable& operator=(NonCopyable&&) = default;
};

class ContainsNC {
    public:
        ~ContainsNC() {
            std::cout << "destruct" << std::endl;
        }
    private:
        NonCopyable nc;
};

int main() {
    std::pair<const int, ContainsNC>(1, ContainsNC());
}

现在,如果注释掉ContainsNC的自定义析构函数,则代码将编译。为什么自定义析构函数会影响std::pair<const int, ContainsNC>的构造?

1 个答案:

答案 0 :(得分:2)

有一条规则说When destructor is defined, move operations are deleted and they are not generated by compiler default.

所以您必须在类中添加move构造函数。

class ContainsNC {
    public:
        ~ContainsNC() {
            std::cout << "destruct" << std::endl;
        }

        ContainsNC(ContainsNC&&) = default;
    private:
        NonCopyable nc;
};

在添加move ctor之后,默认的构造函数被删除,您还必须提供它来编译代码:

class ContainsNC {
    public:
        ~ContainsNC() {
            std::cout << "destruct" << std::endl;
        }
        ContainsNC() = default;
        ContainsNC(ContainsNC&&) = default;
    private:
        NonCopyable nc;
};

您可以检查this link来查看编译器何时为类默认值生成了移动操作。