【问题标题】:Unordered map vs mapUnordered_map 与地图
【发布时间】:2020-12-06 10:13:46
【问题描述】:

有谁知道为什么Dict 类无效但Dict2 没问题?


#include <string>
#include <unordered_map>
#include <map>
#include <variant>

class Dict
{
public:
    Dict() {}

private:
    std::unordered_map<std::string, std::variant<Dict, std::string>> data;
};

class Dict2
{
public:
    Dict2() {}

private:
    std::map<std::string, std::variant<Dict2, std::string>> data;
};

int main()
{
    Dict d;
    Dict2 d2;
    return 0;
}

我得到一个错误

‘value’ is not a member of ‘std::is_trivially_move_constructible&lt;Dict&gt;’.

我查找了普通移动和复制构造的概念,据我所知,应该定义或删除移动构造函数。 我猜这是因为使用std::unordered_mapstd::variant 并且编译器不知道应该如何移动对象。但我不确定我是否理解正确。

【问题讨论】:

    标签: c++ dictionary c++17 unordered-map std-variant


    【解决方案1】:

    我相信这两种情况下的行为都是未定义的。 Dict2 只是偶然执行编译; “似乎有效”是未定义行为的一种可能表现形式。

    [res.on.functions]/1 在某些情况下(替换函数、处理函数、对用于实例化标准库模板组件的类型的操作),C++ 标准库依赖于由一个 C++ 程序。如果这些组件不符合其要求,则本国际标准不要求 实施。

    [res.on.functions]/2 特别是,在以下情况下效果未定义:
    ...
    (2.5) — 如果在实例化模板组件时将不完整类型 (6.9) 用作模板参数,除非该组件特别允许。

    DictDict2 是不完整的类型,直到它们的定义的右大括号。 std::variant 不允许使用不完整的类型进行实例化。

    【讨论】:

    • 感谢您的回答。那么如何建议解决这个问题呢?我还使用std::map 进行了进一步测试,它的行为符合我的预期。我可以创建一个指向std::stringkey1 和一个指向模仿链表行为的同一类的对象的key2。但是我不能用std::unordered_map 来做这件事,因为它不能编译。
    • 好吧,作为一种快速解决方法,您可以在堆上分配嵌套的Dict,如std::variant&lt;std::unique_ptr&lt;Dict&gt;, std::string&gt;std::unique_ptr 明确允许不完整类型作为参数。
    猜你喜欢
    • 2020-02-27
    • 1970-01-01
    • 2014-07-04
    • 2013-01-30
    • 2017-03-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    • 2016-07-23
    相关资源
    最近更新 更多