是否可以将X的容器声明为X的成员

时间:2019-01-05 12:58:01

标签: c++

我上了这个课:

#include <unordered_map>

    class MyClass
    {
        // Trie node class
        struct Node
        {
            std::unordered_map<char, Node> m_children;
            // ...

        }; // .....
};
int main()
{
    MyClass m;
}

编译时出现此错误:

  

/ usr / include / c ++ / 7 / bits / stl_pair.h:204:11:错误:‘std :: pair <_T1,   _T2> :: second”的类型不完整          _T2秒; /// @c second是第二个对象的副本              ^ ~~~~~ AutocompleteModern.cpp:24:12:注意:“ struct Autocomplete :: Node”的前向声明        结构节点               ^ ~~~

我知道,如果将指针用作哈希映射中的值,则可能会起作用。但是我想知道是否有可能在不更改哈希图值的类型的情况下编译上面的代码。还是不可能?

3 个答案:

答案 0 :(得分:5)

您有一个循环依赖项:您说m_children应该包含Node个对象,但是此时尚未定义类Node(仅声明了)。

您可以使用指针(或引用)来完成不完整的类型:

std::unordered_map<char, std::unique_ptr<Node>> m_children;

请注意std::unique_ptr的使用,这用于指示该地图是Node对象的唯一所有者(并且还具有一些自动内存管理的优点)。

答案 1 :(得分:4)

某些一些容器是可能的,但是std::unordered_map不是其中之一。它可以与某些实现一起使用,但该标准并不要求它适用于std::unordered_map(实际上,它说它尚未定义)。因此,即使今天使用特定的编译器进行编译,它明天也可能无法正常工作。

可以声明为不完整类型的容器为std::forward_liststd::liststd::vector。因此,在类定义完成之前,这些容器可以用作类的成员)

答案 2 :(得分:2)

  

但是我想知道是否有可能在不更改哈希图值的类型的情况下编译上面的代码。还是不可能?

这是不可能的,因为编译器无法为该sizeof计算有意义的MyClass

让自己陷入编译器的困境:在编译代码时,它必须计算布局,并为sizeof的字节大小(由MyClass给定)。而且显然不能。

在C ++中,为了实现这种圆形性,您必须使用指针(但是您可以将它们“隐藏”为智能指针,等等)。

(因此,此答案是Some programmer dude's answer的基本原理或直觉)

还有另一个(纯粹是“合法”)原因:C ++ 11标准n3337禁止这样做。我让你检查一下(并确切地找到那里禁止的条款)。

PS。正如songyanyo所评论的那样,您可能会在接受代码的some specific C++ standard library实现中发现(我想在这样的实现中,会使用更多的隐藏指针) 。在我的Linux Debian Sid盒(GCC 8和Clang 7)上不是这种情况。在实践中,您想编写可在您的机器上编译的代码。我不知道哪个特定的C ++标准库最符合该标准,但是上面的直觉仍然存在。