首页 > 解决方案 > 使用已删除的副本存储结构并将构造函数移动到容器中

问题描述

我有一个带有已删除副本和移动构造函数和运算符的结构,但我想将此结构添加到容器中。我怎么解决这个问题?

class NonCopyable {
public:
    NonCopyable() = default;
    NonCopyable(NonCopyable &&) = default;
    NonCopyable(const NonCopyable&) = delete;
    NonCopyable& operator=(const NonCopyable&) = delete;
    NonCopyable& operator=(NonCopyable&&) = default;
};

class NonMovable {
public:
    NonMovable() = default;
    NonMovable(NonMovable &&) = delete;
    NonMovable(const NonMovable&) = default;
    NonMovable& operator=(const NonMovable&) = default;
    NonMovable& operator=(NonMovable&&) = delete;
};

struct Data : NonCopyable, NonMovable
{
    Data(std::string str, int data)
        : m_str(std::move(str)), m_data(data) {}
private:
    std::string m_str;
    int m_data; 
};

int main(int argc, char** argv)
{
    std::unordered_map<std::string, Data> table;
    table.emplace("test", Data{"data",10});
    return 0;
}

错误:

 /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:1881:31: error: no matching constructor for initialization of 'std::__1::pair<const std::__1::basic_string<char>, Data>'
    ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);

标签: c++

解决方案


table.emplace("test", Data{"data",10})仍然会调用移动构造函数Data,你需要使用std::piecewise_construct 来构造pair

std::unordered_map<std::string, Data> table;
table.emplace(std::piecewise_construct, 
              std::make_tuple("test"), 
              std::make_tuple("data",10));

演示。

根据cppreference

 template<class... Args1, class... Args2>
 constexpr pair(std::piecewise_construct_t,
                std::tuple<Args1...> first_args,
                std::tuple<Args2...> second_args);

将 的元素转发first_args给 的构造函数,first并将 的元素转发second_args给 的构造函数second。这是唯一可用于创建一对不可复制、不可移动类型的非默认构造函数。


推荐阅读