`std :: pair` second`的类型不完整,带有`unordered_map`树 [英] `std::pair` `second` has incomplete type with `unordered_map` tree

查看:327
本文介绍了`std :: pair` second`的类型不完整,带有`unordered_map`树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在查看我的一些较旧的代码,并且看到了使用指针来实现 Variant 对象树的代码。这是一棵树,因为每个 Variant 可以包含 Variant * unordered_map $ c>。

I was reviewing some older code of mine and I saw the code using pointers to implement a tree of Variant objects. It is a tree because each Variant can contain an unordered_map of Variant*.

我看了一下代码,想知道为什么不只使用值,一个 std :: vector< Variant> std :: unordered_map< std :: string,Variant> ,而不是 Variant *

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*.

所以我继续进行了更改。似乎没事,只有一件事,我错误

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.

我以为这早一点可行了,但实际上却没有,我使用HideMap在上忘记了 :: type ...

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

所以,我的问题是,为什么<$ c $可以正常工作c> vector 而不是 unordered_map

So, my question is, why does it work okay for vector and not unordered_map?

如果问题是无法使用不完整的类型,是否有办法延迟 unordered_map 的实例化?我真的不希望每个对象属性都是单独的 new 分配。

If the problem is the inability to use incomplete types, is there a way to delay the instantiation of the unordered_map? I really don't want every object property to be a separate new allocation.

推荐答案

这将使用new放置将 Union 的初始化推迟到构造函数,其中 Variant 是完整类型。您需要使用 Union 的任何地方 reinterpret_cast 。我努力不违反任何严格的对齐规则。

This uses placement new to defer the initialization of the Union to the constructor where Variant is a complete type. You need to reinterpret_cast everywhere you need to use the Union. 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;
}

这篇关于`std :: pair` second`的类型不完整,带有`unordered_map`树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆