2016-12-21 11 views
1

このコードはエラーなしでコンパイルされますが、期待どおりに動作するかどうかは疑問です。そのようなネスティングは許可されていますか?私はboostとC++を使うことはできません。C++:それが属するクラスを含む共用体

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();  
}; 
+3

組合は、コンストラクタとデストラクタを処理しません。したがって、非PODでの共用体の使用は安全ではありません(std :: vectorは安全ではありません)。 std :: variantとboost :: variantを参照してください。 –

+3

質問には関係ありませんが、なぜ 'typedef struct ... 'を使用していますか?構造体はクラスに似ており、構造体名はクラス名のような型です。 –

+1

私はCの世界から来たので。 – Ariel

答えて

-2

編集 私のオリジナルの答えは、plzはそれを無視し、誤解を招く/間違っていました。理由は以下のコメントを参照してください。とにかくstd :: variantまたはboost :: variantを受け入れます。

Non PlainOldData(POD)は、c-unionでは安全ではありません。

特にこのproplem std :: variantは、C++ 17標準になりました。以前のバージョンのC++にboost :: variantを使用することができます。

問題は、その組合がコンストラクタとデストラクタについて何も知らないことです。したがって、必要となるよりユニオンの要素でより一般的なことを行うことはできません(動的メモリ割り当てなど)

+0

downvoteで私を助けてください?私が言ったことは間違っていますか? –

+0

単純な型を持たない共用体を作成して使用することができます。 'boost :: variant' /' std :: variant'へのリダイレクトは賢明ですが、「不可能」は偽です。どのようにしても、どのように共用体を管理するかは、 'std :: vector'を通してクラス自体をネストできるかどうかとは無関係です。 – Quentin

+0

些細ではないものが好きですか?私はまだstd :: variantをクラスに使用するのが賢明だと思います、それはありませんか? –

5

予想通りに動作するかどうかは疑問です。

あなたは正しいです。それはできません。まず、Nodeを構築しようとすると実際にはコンパイルされません。 unionで、任意の非自明な操作が暗黙のうちに削除されるためです

prog.cc:26:10: error: call to implicitly-deleted default constructor of 'Node' 
    Node n; 
     ^

:あなたのような何かを得るでしょう。正しいことをするには、~Value()を定義する必要があります。これは、typeが、実際にはどのユニオンの要素のインデックスであると仮定し、それをオンにして適切なデストラクタを呼び出します。そして、コピーしたり動かすのと同じことをしてください。

しかし、不完全なタイプのネストもOKではありません。 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>>; 

このタイプはすでに破壊可能、コピー可能、移動可能、訪問可能です。

関連する問題