67

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

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

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

4

3 に答える 3

82

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

これは基本的な情報隠蔽であり、C++に不可欠なスキルです。勉強しなさい!

ここでの最高得票数の回答は完全に間違っており、人々が実際にソースを調べてその事実を確認するのではないかと疑っています。これは、f()関数で任意の型をラップするanylikeインターフェイスの基本的な実装です。呼び出せるようにします。

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関数への他の情報アクセスを提供して機能することを除いて、同じ基本的なことを行います。

于 2011-02-14T05:35:28.077 に答える
19

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

Boostがインストールされている場合は、「any.hpp」と「variant.hpp」にソースファイルが表示されるはずです。インストールされているヘッダーが見つかるまで、「/ usr」、「/ usr / local」、「/ opt/local」で「include/boost/variant.hpp」と「include/boost/any.hpp」を検索します。あなたは見てみることができます。

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

于 2011-02-14T05:00:11.633 に答える
8

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

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

于 2011-02-14T05:13:21.847 に答える