std::variant 和 boost::variant 有什么区别?

What are the differences between std::variant and boost::variant?

answer 这个 SO 问题中:

What is the equivalent of boost::variant in the C++ standard library?

有人提到 boost::variantstd::variant 有点不同。

(动机是在 C++17 之前的代码中使用 boost::variant

似乎关于变体设计的主要争论点 class 是当对变体的赋值(完成后应销毁旧值)抛出异常时应该发生什么:

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

选项似乎是:

  • 通过将可能的可表示类型限制为不可抛出移动构造的类型来防止这种情况。
  • 保留旧值 - 但这需要双缓冲区。
  • 在堆上构造新值,将指向它的指针存储在变体中(因此变体本身即使在异常时也不会乱码)。显然,这就是 boost::variant 所做的。
  • 有一个 'disengaged' 状态,每个变体都没有值,并在出现此类故障时转到该状态。
  • 未定义的行为
  • 在类似情况发生后尝试读取其值时使变体抛出异常

如果我没记错的话,后者是被接受的。

这是 Axel Naumann 于 2015 年 11 月在 ISO C++ 博客 post 中总结的内容。

  • Assignment/emplacement 行为:

    • boost::variant 可能 allocate memory when performing assignment into a live variant. There are a number of rules that govern when this can happen,因此 boost::variant 是否分配内存取决于它实例化的 Ts

    • std::variant 永远不会 动态分配内存。但是,作为对C++对象复杂规则的让步,如果一个assignment/emplacement抛出,那么variant 可能进入"valueless_by_exception"状态。在此状态下,无法访问 variant,也无法访问任何其他用于访问特定成员的函数。

      只有assignment/emplacement抛出才能进入该状态

  • Boost.Variant 包括 recursive_variant,其中 allows a variant to contain itself。它们本质上是围绕指向 boost::variant 的指针的特殊包装器,但它们与访问机制相关联。

    std::variant 没有这样的助手类型。

  • std::variant 提供对 post-C++11 功能的更多使用。例如:

std::variant 与 boost::variant

略有不同
  • std::variant 在头文件中而不是在
  • 中声明
  • std::variant 从不分配内存
  • std::variant 可与 constexpr
  • 一起使用
  • 不用写boost::get(&variable),你必须写std::get_if(&variable) for std::variant
  • std::variant 无法递归保持自身并错过了其他一些高级技术
  • std::variant 可以就地构建对象
  • std::variant 有 index() 而不是 which()