【问题标题】:std::map emplace non-movable non-copyable non-default-constructible typestd::map emplace 不可移动不可复制非默认构造类型
【发布时间】:2020-05-15 15:18:36
【问题描述】:

我想要一个没有复制 ctor、没有移动 ctor 和默认 ctor 的类的映射(我无法控制这个类)。

我尝试过将 std::map::emplace 与 std::piecewise_construct 和 std::forward_as_tuple 参数一起使用,但编译器似乎告诉我这是不可能的,因为它首先尝试默认构造。

// Example program
#include <iostream>
#include <string>
#include <map>
#include <utility>
#include <tuple>

class stone
{
public:
    stone() = delete;
    stone(stone& s) = delete;
    stone(stone&& s) = delete;
    stone(const std::string& s) : str(s)
    {
    }
    std::string str;
};

int main()
{
    std::map<int, stone> m;
    m.emplace(std::piecewise_construct, std::forward_as_tuple(5), std::forward_as_tuple("asdf"));
    std::cout << "map[5]: " << m[5].str << "\n";
}

在此处查看编译器错误示例:http://cpp.sh/8bbwh

我怎样才能做到这一点?我试过查看类似的问题,但它们似乎没有包含任何对我的特定场景有用的答案。

【问题讨论】:

    标签: c++ c++11 stdmap


    【解决方案1】:

    emplace 操作没有问题,但问题在于 std::map::operator[],因为它要求 value_type 是默认可构造的。但是,stone 有一个已删除的默认构造函数。

    相反,您可以使用没有该要求的std::map::at

    std::cout << "map[5]: " << m.at(5).str << "\n";
    

    这是demo

    【讨论】:

    • 选择这个答案是因为它专注于真正阻碍我的例子,为演示 +1。
    • 另请注意,9.1 中修复了一个 gcc 错误,因此必须在早期版本中解决这种情况
    【解决方案2】:

    std::map emplace 不可移动不可复制非默认构造类型

    像这样:

    m.emplace(5, "asdf");
    

    不需要 std::piecewise_construct 或 std::forward_as_tuple。


    至于查找值,您不能使用下标运算符,因为这要求类型是默认可构造的 - 当值在查找之前不在地图中时,将使用默认构造。

    要查找非默认可构造类型,您必须改用 map::find 或 map::at。前者返回迭代器结束,后者如果映射的值不存在则抛出异常。

    【讨论】:

    • 你是对的,在这种情况下,piecewise_construct 确实是不必要的。
    猜你喜欢
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 2019-04-01
    • 2012-07-30
    • 2020-05-19
    • 2022-01-13
    • 1970-01-01
    相关资源
    最近更新 更多