6

これに用語があるかどうかはわかりませんが、「選択」が機能しているようです。私は C++ で作業しており、作成する必要がある共用体がたくさんあります。共用体は、共用体のメンバーの 1 つの選択を表します。現在の「選択」は追跡され、常に利用可能です。私は現在、これらの「ユニオン」を手動でコーディングしていますが、この種のことを (半) 自動的に行うための巧妙なトリックがあるかどうか疑問に思っています。

これを実装しようとする最初の試合で、代入演算子のオーバーロード、自明でないコンストラクター、またはコピー コンストラクターがないというユニオンの制限に遭遇しましたが、現在の「選択」を実際に追跡しているため、非常に定義された動作があることに気付きました。ほぼすべての状況下で使用できます。

これが私が現在行っていることです (2 つの選択肢のみで、最大 10 または 15 になる可能性があります)。これはかなりの量のコードであり、そのほとんどすべてがボイラープレートです。また、私が以下に持っているものが有効であるかどうかについてコメントがあれば、それは素晴らしいことですが、それでもC ++の狂気の一部を拾っています...

struct MyChoice
{
    struct Choice1
    {
        int a;
        char* b;
    };

    struct Choice2
    {
        bool c;
        double d;
    };

    enum Choice
    {
        Choice_Choice1,
        Choice_Choice2
    } choice;

    char _value[max(sizeof(Choice1),sizeof(Choice2))]; // could be private
    Choice1& choice1()
    {
        if(choice == Choice_Choice2)
        {
            (*(Choice2*)_value)->~Choice2();
            (*(Choice1*)_value) = Choice1();
            choice = Choice_Choice1;
        }
        return *(Choice1*)_value;
    }
    Choice2& choice2()
    {
        if(choice == Choice_Choice1)
        {
             (*(Choice1*)_value)->~Choice1();
             (*(Choice2*)_value) = Choice2();
             choice = Choice_Choice2; 
        }
        return *(Choice2*)_value;
    }
    MyChoice()
    {
       _choice = Choice_Choice1;
       (*(Choice1)_value) = Choice1();
    }
    MyChoice(const MyChoice& other)
    {
       this->_choice = other.choice;
       if(this->_choice == Choice_Choice1)
          (*(Choice1*)_value) = other.choice1();
       else
          (*(Choice2*)_value) = other.choice2();
    }
    ~MyChoice()
    {
        if(_choice == Choice_Choice1)
            (*(Choice1)_value)->~Choice1();
        else
            (*(Choice2)_value)->~Choice2();
    }
};

助けてくれてありがとう

4

4 に答える 4

15

boost::any と boost::variant を調べてみてください。最初のものを使用すると、boost::any 変数に任意の型を挿入して、その型を追跡できます。それは「実行時チェック」タイプです。2 番目のものは、挿入するすべての型を定義することを強制します (つまり、boost::variant < Choice1, Choice2, ... > ) が、コンパイル時により多くの型チェックを強制します。

両方とも、異なるタイプのオブジェクトを格納するために使用されます。たとえば、異種のコンテインメント (std::vector は std::string または int を処理できます) などです。

于 2010-07-21T21:31:36.510 に答える
6

より一般的には、これは「識別されたユニオン」またはタグ付きユニオンです。前述のように、boost::variant または boost::any はどちらもこの戦略の実装です。

于 2010-07-21T21:33:54.913 に答える
3

あなたが私のようで、一般的に継承よりもバリアントを好む場合でも (私は ML のような人です)、継承はそれを行う C++ の方法です。

のオブジェクトを使用する代わりに、 のオブジェクトboost::variant<Apple, Pear, Banana>へのスマート ポインターを使用しますFruit。継承にはオープンであるという利点があります。いつでもより多くの型を追加できますFruit。通常、仮想メソッドは、スイッチや if ステートメントよりもはるかにクリーンです。継承にチャンスを与えてください。あなたはそれを好きになることを学ぶでしょう。

于 2010-07-21T21:52:26.267 に答える