C++:包含它所属的类的联合

Ari*_*iel 1 c++ clang unions c++11

虽然这个代码编译没有任何错误,但我怀疑它将按预期工作.允许这样的嵌套吗?我不能使用boost和c ++ 17.

class Node;

typedef struct Value {      
    ValueTag type;

    union {         
        std::int32_t                          integerValue;
        std::float_t                          floatValue;
        bool                                  boolValue;
        std::vector<Node>                     arrayValue;
        std::unordered_map<std::string, Node> dictionaryValue;
    };          
} Value;

class Node {                
private:        
    Value m_value;          
public:                 
    virtual ~Node();    
};
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 5

我怀疑它会按预期工作.

你是对的.它不会.首先,如果您尝试构建一个,它将不会实际编译Node.你会得到类似的东西:

prog.cc:26:10: error: call to implicitly-deleted default constructor of 'Node'
    Node n;
         ^
Run Code Online (Sandbox Code Playgroud)

这是因为在a中union,隐式删除了任何非平凡的操作.你必须定义~Value()做正确的事情.其中,假设type是我们实际所在的联合元素的索引,打开它并调用适当的析构函数.然后为复制和移动做同样的事情.

也就是说,不完整类型的嵌套也不行.vector只要在第一次使用之前完成,就可以使用不完整的类型.但是unordered_map没有这个津贴.你必须将值类型包装在其他东西中 - 比如unique_ptr<Node>shared_ptr<Node>.

你所拥有的Value是一种具有百万个不同名称的常见模式:有区别的联合,总和类型,或者最常见的variant.我建议你改用std::variant(如果你使用的是最近的编译器来支持这样的事情)或boost::variant(否则),而不是重新发明轮子.有了这个,你有:

using Value = variant<int32_t, float, bool,
    std::vector<Node>, std::unordered_map<std::string, Node>>;
Run Code Online (Sandbox Code Playgroud)

这种类型已经可以破坏,可复制,移动,并且可以访问.