2010-12-06 9 views
6

私はtypedef boost::variant<int, float, double, long, bool, std::string, boost::posix_time::ptime> variantを持っています。これは構造体に異なる型の値を格納するために使用します。特定の型のうちの1つだけが構造体に格納されますが、バリアントから実際の型を取得するために必要なこれらの構造体のベクトルがあります。私はタイプこのバリアントのうち、変換を行う必要があるときは一般的にboost :: variantから<T>に変換します。

は今、私はこれを行う:

variant second = mystruct.variant; 
           if (second.which() == 5) //string 
        { 
         std::string val = boost::get<std::string>(second); 
         modvalue->AddNodeAttribute(key, val); 
        } 
        else if (second.which() == 0) //int 
        { 
         int val = boost::get<int>(second); 
         modvalue->AddNodeAttribute(key, val); 
        } 
        else if (second.which() == 2) //double 
        { 
         double val = boost::get<double>(second); 
         modvalue->AddNodeAttribute(key,val); 
        } 
        else if (second.which() == 1) //float 
        { 
         float val = boost::get<float>(second); 
         modvalue->AddNodeAttribute(key, val); 
        } 
        else if (second.which() == 3) // long 
        { 
         long val = boost::get<long>(second); 
         modvalue->AddNodeAttribute(key, val); 
        } 
        else if (second.which() == 4) // bool 
        { 
         bool val = boost::get<bool>(second); 
         modvalue->AddNodeAttribute(key, val); 
        } 
        else if (second.which() == 6) // posix::time 
        { 
         boost::posix_time::ptime ptm = boost::get<boost::posix_time::ptime>(second); 
         modvalue->AddNodeAttribute(key, ptm); 
        } 

私は一般的な機能を書くことでこれをやって周りに取得することができ、より一般的な方法があるかどうか、私は疑問に思っていますバリアントと戻り値であるタイプTをとります。しかし、私がそれをするとき、私はまだそれぞれのタイプのTの説明のために同様の文を書く必要があります

FromVariant<int>(var);のようなものですが、私はまだ私の変種の各タイプのためにそれを行う必要があります。

私の一般的な解決策はコードを減らすことはできませんが、それを増やすことは明らかですが、それは明らかに重要ではありません。誰かが私の変種の中からいろいろな型を取り除くより洗練された解決法を持っているのかどうか、私はちょうど私が元に戻したい型を与える関数を呼び出すことができますか?

答えて

11

は別のオプションです - 再び使用するように...

struct add_node_visitor : boost::static_visitor<> 
{ 
    add_node_visitor(<type of modvalue> & node, <type of key> & key) : _node(node), _key(key) {} 

    template <typename _Item> 
    void operator()(_Item const& item) 
    { 
    node->AddNodeAttribute(_key, item); 
    } 

    <type of modvalue> & _node; 
    <type of key> & _key; 
} 

を訪問者の使用に基づく:限り、あなたのAddNodeAttributeがためのオーバーロードがありますよう

boost::apply_visitor (add_node_visitor(modmodvalue, key), mystruct.variant); 

すべての型、上記は動作するはずです...

+0

ええ、 'static_visitor'はこの正確な問題を解決するためのものです。 :) – jalf

+0

あなたには些細かもしれませんが...私にはありません... –

+0

@Tony、私の答えを変えました - 申し訳ありませんが、私は他のアプローチのコードを出すことができませんでした(それは私のコードベースの仕事です!私はあなたのケースにもっと適していると思います。たとえば、構造体のすべてのフィールドで 'apply_visitor'を呼び出すことができます... – Nim

2

私がboost::variantを使用していたとき、私は常に訪問者の技術を使用して含まれているデータにアクセスしました。私の意見では、これは非常にエレガントな方法です。スイッチ論理には依存しません。これは実際には悪い設計の兆候です。 documentationを参照してください。

幸運を祈る!実はここに、いくつかのより多くのあなたのコードを見て

+0

これ以上の事例はありますか? –

+0

ここに、一見して見栄えのよいサンプルがあります:http://en.highscore.de/cpp/boost/datastructures.html。下にスクロールして 'boost :: apply_visitor'がどのように動作するかを見てください。 –

0

... AddNodeAttributeとは何ですか?基本的には、それぞれのタイプについて同じことでしょうか?どこかのノード属性のコンテナがあれば、基本的にバリアント型のコンテナにする必要があります。

... AddNodeAttributeをバリアントを受け入れる単一の関数に書き直さないのはなぜですか?

+0

私はバリアントではなくバリアントで実際のタイプが必要なためです。それ以外の場合は、後で変換を行う必要があります。 –

+0

値を使って何をしているのか詳しく説明してください。 –

関連する問題