【C++】C++17 std::variant的用法

c++17中引入了std::variant。std::variant类似union。

定义于头文件 <variant>。

类模板 std::variant 表示一个类型安全的联合体。 std::variant 的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误情况下无值(此状态难以达成,见 valueless_by_exception )。

与联合体在聚合初始化中的行为一致, 若 variant 保有某个对象类型 T 的值,则直接于 variant 的对象表示中分配 T 的对象表示。不允许 variant 分配额外的(动态)内存。

variant 不容许保有引用、数组,或类型 void 。空 variant 亦为病式(可用 std::variant<std::monostate> 代替)。

variant 容许保有同一类型多于一次,而且可保有同一类型的不同 cv 限定版本。

同联合体,默认构造的 variant 保有其首个选项的值,除非该选项不是可默认构造的(该情况下 variant 亦非可默认构造:能用辅助类 std::monostate 使这种 variant 可默认构造)。

简单示例:

using IntFloatString = std::variant<int, float, std::string>; // 定义支持int、float、string三个类型,并取一个别名
//初始化一个variant
TEST_F(InitVariant) {

    IntFloatString i = 10;
    ASSERT_EQ(10, std::get<int>(i) );

    IntFloatString f = 20.0f;
    ASSERT_EQ(20.0f, std::get<float>(f) );

    IntFloatString s = "hello world";
    ASSERT_EQ("hello world", std::get<std::string>(s));
}
模板形参

Types - 可存储于此 variant 中的类型。所有类型必须满足可析构 (Destructible) 要求(特别是不允许数组类型和非对象类型)。

成员函数

(构造函数):构造 variant 对象(公开成员函数)

(析构函数):析构 variant 同其所含的值(公开成员函数)

operator=:赋值 variant(公开成员函数)

观察器

index:返回 variant 所保有可选项的零基下标(公开成员函数)

valueless_by_exception:检查 variant 是否在非法状态(公开成员函数)

修改器

emplace:原位构造 variant 中的值(公开成员函数)

swap:与另一 variant 交换(公开成员函数)

实例
#include <variant>
#include <string>
#include <cassert>
 
int main()
{
    std::variant<int, float> v, w;
    v = 12; // v 含 int
    int i = std::get<int>(v);
    w = std::get<int>(v);
    w = std::get<0>(v); // 与前一行效果相同
    w = v; // 与前一行效果相同
 
//  std::get<double>(v); // 错误: [int, float] 中无 double
//  std::get<3>(v);      // 错误:合法下标值为 0 与 1
 
    try {
      std::get<float>(w); // w 含 int 而非 float :将抛出
    }
    catch (const std::bad_variant_access&) {}
 
    using namespace std::literals;
 
    std::variant<std::string> x("abc"); // 转换构造函数在无歧义时起作用
    x = "def"; // 转换赋值在无歧义时亦起作用
 
    std::variant<std::string, void const*> y("abc");
    // 传递 char const * 时转换成 void const *
    assert(std::holds_alternative<void const*>(y)); // 成功
    y = "xyz"s;
    assert(std::holds_alternative<std::string>(y)); // 成功
}

可以看看:

https://github.com/boostorg/variant/tree/develop/include/boost

参考

https://zh.cppreference.com/w/cpp/utility/variant

发布了467 篇原创文章 · 获赞 14 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/LU_ZHAO/article/details/105579327