バリアントとブーストライブラリのいずれかが内部でどのように機能しますか?私が取り組んでいるプロジェクトでは、現在、タグ付きユニオンを使用しています。 C++の共用体では、コンストラクタ、デストラクタ、またはオーバーロードされた代入演算子でオブジェクトを使用できないため、別のものを使用します。
Anyおよびvariantのサイズを照会し、それらを使用していくつかの実験を行いました。私のプラットフォームでは、variantは可能な限り長い型に8バイトを加えたサイズを取ります。型情報と残りの値は8バイトだけだと思います。一方、anyは8バイトだけです。私は64ビットプラットフォームにいるので、どれもポインタを保持しているだけだと思います。
Anyはどのタイプを保持しているかをどのようにして知るのですか? Variantは、テンプレートを介してどのように機能しますか?これらのクラスを使用する前に、これらのクラスについて詳しく知りたいと思います。
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関数へのその他の情報アクセスを提供します。
boost::any
とboost::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
を統合しますタイプ。
boost::any
は、テンプレートコンストラクターの実行中にtypeinfo
のスナップショットを作成します。typeinfoへのアクセスを提供する非テンプレートベースクラスへのポインターがあり、コンストラクターはそのインターフェイスを満たすタイプ固有のクラスを派生します。同じ手法を実際に使用して、一連のタイプの他の一般的な機能(ストリーミング、一般的な演算子、特定の機能など)をキャプチャできますが、boostはこれを制御できません。
boost :: variantは概念的には以前に行ったことと似ていますが、文字通りunion
を使用せず、代わりにバッファ内のオブジェクトの配置構築/破棄に手動でアプローチします(アライメントの問題を明示的に処理します)これは、C++が実際のunion
sに複雑な型を持っているという制限を回避します。