web-dev-qa-db-ja.com

boost :: variantとboost :: anyはどのように動作しますか?

バリアントとブーストライブラリのいずれかが内部でどのように機能しますか?私が取り組んでいるプロジェクトでは、現在、タグ付きユニオンを使用しています。 C++の共用体では、コンストラクタ、デストラクタ、またはオーバーロードされた代入演算子でオブジェクトを使用できないため、別のものを使用します。

Anyおよびvariantのサイズを照会し、それらを使用していくつかの実験を行いました。私のプラットフォームでは、variantは可能な限り長い型に8バイトを加えたサイズを取ります。型情報と残りの値は8バイトだけだと思います。一方、anyは8バイトだけです。私は64ビットプラットフォームにいるので、どれもポインタを保持しているだけだと思います。

Anyはどのタイプを保持しているかをどのようにして知るのですか? Variantは、テンプレートを介してどのように機能しますか?これらのクラスを使用する前に、これらのクラスについて詳しく知りたいと思います。

65
salvador p

Boost :: anyドキュメントを読むと、アイデアのソースが提供されます。 http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf

これは基本的な情報隠蔽であり、必須のC++スキルです。学べ!

ここで最も投票数の多い答えは完全に間違っており、人々が実際にソースを見てその事実を確認するのではないかと疑っています。ここで、任意のタイプをf()関数を呼び出して呼び出すことができます:

struct f_any
{
   f_any() : ptr() {}
   ~f_any() { delete ptr; }
   bool valid() const { return ptr != 0; }
   void f() { assert(ptr); ptr->f(); }

   struct placeholder
   {
     virtual ~placeholder() {}
     virtual void f() const = 0;
   };

   template < typename T >
   struct impl : placeholder
   {
     impl(T const& t) : val(t) {}
     void f() const { val.f(); }
     T val;
    };
   // ptr can now point to the entire family of 
   // struct types generated from impl<T>
   placeholder * ptr;

   template < typename T >
   f_any(T const& t) : ptr(new impl<T>(t)) {}

  // assignment, etc...
};

boost :: anyは、f()が実際にtypeinfo const&そして、動作するany_cast関数へのその他の情報アクセスを提供します。

78
Edward Strange

boost::anyboost::variantの主な違いは、anyは任意の型を格納できるのに対し、variantは列挙型のセットの1つのみを格納できることです。 any型には、オブジェクトへのvoid*ポインターと、基になる型を記憶し、ある程度の型の安全性を確保するためのtypeinfoオブジェクトが格納されます。 boost::variantでは、最大サイズのオブジェクトを計算し、「プレースメントnew」を使用してこのバッファー内にオブジェクトを割り当てます。また、タイプまたはタイプインデックスも保存します。

Boostがインストールされている場合、「any.hpp」および「variant.hpp」のソースファイルを確認できることに注意してください。インストールされたヘッダーが見つかるまで、「/ usr」、「/ usr/local」、および「/ opt/local」で「include/boost/variant.hpp」および「include/boost/any.hpp」を検索します。ご覧ください。

編集
以下のコメントで指摘されているように、boost :: anyの説明にはわずかな不正確さがありました。 void*(およびポインタを適切に削除するテンプレート化された破棄コールバック)を使用して実装できますが、実際の実装はany<T>::placeholder*を使用し、any<T>::holder<T>のサブクラスとしてany<T>::placeholderを統合しますタイプ。

20

boost::anyは、テンプレートコンストラクターの実行中にtypeinfoのスナップショットを作成します。typeinfoへのアクセスを提供する非テンプレートベースクラスへのポインターがあり、コンストラクターはそのインターフェイスを満たすタイプ固有のクラスを派生します。同じ手法を実際に使用して、一連のタイプの他の一般的な機能(ストリーミング、一般的な演算子、特定の機能など)をキャプチャできますが、boostはこれを制御できません。

boost :: variantは概念的には以前に行ったことと似ていますが、文字通りunionを使用せず、代わりにバッファ内のオブジェクトの配置構築/破棄に手動でアプローチします(アライメントの問題を明示的に処理します)これは、C++が実際のunionsに複雑な型を持っているという制限を回避します。

9
Tony Delroy