web-dev-qa-db-ja.com

std :: variantとboost :: Variantの違いは何ですか?

回答 これに対するSO質問:

C++標準ライブラリのboost :: Variantに相当するものは何ですか?

boost::variantstd::variantは多少異なると言われています。

  • これらのクラスを使用している人に関する限り、違いは何ですか?
  • これらの違いでstd::variantを採用するために、委員会はどのような動機を表明しましたか?
  • これらのいずれかでコーディングする場合、もう一方への切り替えとの最大の互換性を維持するために、何に注意する必要がありますか?

(動機は、C++ 17より前のコードでboost::variantを使用することです)

15
einpoklum
  • 割り当て/定置動作:

    • boost::variant may 割り当てを実行するときにメモリを割り当てます ライブvariantに。 これがいつ発生するかを管理するいくつかのルール があるため、boost::variantがメモリを割り当てるかどうかは、インスタンス化されるTsによって異なります。

    • std::variant決して動的にメモリを割り当てません。ただし、C++オブジェクトの複雑なルールへの譲歩として、割り当て/配置がスローされた場合、variantmayは「 valueless_by_exception "状態。この状態では、variantにアクセスできず、特定のメンバーにアクセスするための他の関数も機能しません。

      この状態に入ることができるのは、割り当て/配置がスローされた場合のみです。

  • Boost.Variantにはrecursive_variantが含まれています。これは variantにそれ自体を含めることができます 。これらは本質的にboost::variantへのポインターの特別なラッパーですが、訪問機構に関連付けられています。

    std::variantにはそのようなヘルパータイプはありません。

  • std::variantは、C++ 11以降の機能をさらに活用します。例えば:

17
Nicol Bolas

バリアントクラスの設計に関する主な論点は、バリアントへの割り当て(完了時に古い値を破棄する必要がある)が例外をスローしたときに何が起こるかということだったようです。

variant<std::string, MyClassWithThrowingDefaultCtor> v = "ABC";
v = MyClassWithThrowingDefaultCtor();

オプションは次のようです。

  • 表現可能なタイプをnothrow-move-constructibleタイプに制限することにより、これを防ぎます。
  • 古い値を保持します-ただし、これにはダブルバッファが必要です(これがboost::variantは明らかにします)。
  • 各バリアントに値のない「解放された」状態を持ち、そのような障害が発生するとその状態になります。
  • 未定義の振る舞い
  • そのようなことが起こった後にその値を読み取ろうとするときにバリアントをスローさせます

私が間違っていなければ、後者が受け入れられています。

これは、2015年11月のAxelNaumannによるISOC++ブログ post から要約されています。

3
einpoklum