简体   繁体   English

`std :: pair``second`具有'unordered_map`树的不完整类型

[英]`std::pair` `second` has incomplete type with `unordered_map` tree

I was reviewing some older code of mine and I saw the code using pointers to implement a tree of Variant objects. 我正在审查我的一些旧代码,我看到代码使用指针来实现Variant对象的树。 It is a tree because each Variant can contain an unordered_map of Variant* . 它是一棵树,因为每个Variant都可以包含Variant*unordered_map

I looked at the code and wondered why isn't it just using values, a std::vector<Variant> , and std::unordered_map<std::string, Variant> , instead of Variant* . 我查看了代码,并想知道为什么不只是使用值, std::vector<Variant>std::unordered_map<std::string, Variant> ,而不是Variant*

So I went ahead and changed it. 所以我继续改变它。 It seemed okay except one thing, I got errors : 看起来好像除了一件事,我有错误

 /usr/local/include/c++/6.1.0/bits/stl_pair.h:153:11: error: 'std::pair<_T1, _T2>::second' has incomplete type _T2 second; /// @c second is a copy of the second object ^~~~~~ main.cpp:11:8: note: forward declaration of 'struct Variant' struct Variant ^~~~~~~ 

So I figured I could trick the compiler into delaying the need to know that type, which didn't work either . 所以我想我可以欺骗编译器延迟知道那种类型的需要,这种方式也不起作用

Working Not Working! 工作不工作! ( MCVE ) MCVE

I thought this worked earlier but it actually doesn't, I forgot ::type on the using HideMap... 我认为这工作得早,但实际上没有,我忘了::typeusing HideMap...using HideMap...

#include <vector>
#include <unordered_map>
#include <iostream>

template<typename K, typename V>
struct HideMap
{
    using type = std::unordered_map<K, V>;
};

struct Variant
{
    using array_container = std::vector<Variant>;

    // Does not work either
    using object_container = typename HideMap<std::string, Variant>::type;

    // Fails
    //using object_container = std::unordered_map<std::string, Variant>;

private:
    union Union
    {
        std::int64_t vint;
        array_container varr;
        object_container vobj;

        // These are required when there are union
        // members that need construct/destruct
        Union() {}
        ~Union() {}
    };

    Union data;
    bool weak;
};

int main()
{
    Variant v;
    std::cout << "Works" << std::endl;
}

So, my question is, why does it work okay for vector and not unordered_map ? 所以,我的问题是,为什么它适用于vector而不是unordered_map

If the problem is the inability to use incomplete types, is there a way to delay the instantiation of the unordered_map ? 如果问题是无法使用不完整类型,是否有办法延迟unordered_map的实例化? I really don't want every object property to be a separate new allocation. 我真的不希望每个对象属性都是一个单独的new分配。

This uses placement new to defer the initialization of the Union to the constructor where Variant is a complete type. 这使用placement new来将Union的初始化推迟到Variant是完整类型的构造函数。 You need to reinterpret_cast everywhere you need to use the Union . 您需要在需要使用Union任何地方reinterpret_cast I made an effort to not have any strict-alignment violations. 我努力不违反任何严格的协议。

#include <algorithm>
#include <iostream>
#include <unordered_map>
#include <vector>

struct Variant {
    Variant();
    ~Variant();

    private:
    std::aligned_union<0, std::vector<Variant>,
                         std::unordered_map<std::string, void *>,
                         std::int64_t>::type data;
};

namespace Variant_detail {
    using array_container = std::vector<Variant>;
    using object_container = std::unordered_map<std::string, Variant>;

    union Union {
        std::int64_t vint;
        array_container varr;
        object_container vobj;

        // These are required when there are union
        // members that need construct/destruct
        Union() {}
        ~Union() {}
    };
}

Variant::Variant() {
    //make sure that std::unordered_map<std::string, Variant> is not too large
    static_assert(sizeof(std::unordered_map<std::string, Variant>) <=
                      sizeof data, "Variant map too big");
    static_assert(alignof(std::unordered_map<std::string, Variant>) <=
                      alignof(decltype(data)), "Variant map has too high alignment");
    auto &my_union = *new (&data) Variant_detail::Union;
    my_union.vint = 42;
}

Variant::~Variant() {
    reinterpret_cast<Variant_detail::Union &>(data).~Union();
}

int main() {
    Variant v;
    std::cout << "Works" << std::endl;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用带有std :: pair枚举类的unordered_map作为键的不完整类型struct std :: hash无效 - Invalid use of incomplete type struct std::hash with unordered_map with std::pair of enum class as key std :: make_pair,std :: unordered_map以及键类型中的move构造函数的用法 - std::make_pair, std::unordered_map and usage of move constructor from key type 使用std :: pair作为键创建std :: unordered_map - Creating an std::unordered_map with an std::pair as key 使用std :: pair作为std :: unordered_map中的键 - Using std::pair as key in std::unordered_map 如何将 std::unordered_map 与 std::pair 一起使用? - How to Use std::unordered_map with std::pair? libstdc ++对std :: unordered_map的支持是否不完整? - Is libstdc++ support for std::unordered_map incomplete? std :: unordered_map不可分配的内部对。 怎么样? - std::unordered_map non assignable internal pair. How? 是否可以将 std::pair 作为 unordered_map 的 T 值? - Is it possible to have std::pair as T value for unordered_map? 构造一个unordered_map,其值是一对字符串和对象类型 - construct an unordered_map with value being a pair of string and object type 为什么std :: map接受std :: pair作为键,但std :: unordered_map不接受? - Why does std::map accept a std::pair as key, but std::unordered_map does not?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM