首页 > 解决方案 > 无法在 C++17 中构造包含 const int 和不可复制(但可移动)对象的对

问题描述

我有一个类,我将其称为 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>

标签: c++c++17

解决方案


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

所以你必须在你的类中添加移动构造函数。

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;
};

您可以检查此链接以查看编译器何时为类默认生成移动操作。


推荐阅读