std::variant

类模板 std::variant 表示一个类型安全的联合体(以下称“变体”)。一个 std::variant 的实例在任意时刻要么保有它的可选类型之一的值,要么在错误情况下无值。

与联合体类似,如果变体保有某个对象类型 T 的值,那么 T 的对象表示会在变体自身的对象表示中直接分配。不允许变体分配额外的(动态)内存。

变体不能保有引用、数组,或类型 void。

与联合体在聚合初始化中的行为一致,默认构造的变体保有它的首个选项的值,除非该选项不可默认构造(此时该变体也不可默认构造)。可以用辅助类 std::monostate 使这种变化体可默认构造。

#include <iostream>
#include <variant>
#include <string>
#include <stdexcept>

class base {
public:
    base() {}
    virtual ~base() {}
    virtual void Show()
    {
        std::cout << "base";
    }
    friend std::ostream& operator<<(std::ostream& os, base& p);

};

std::ostream& operator<<(std::ostream& os, base& p)
{
    p.Show();
    return os;
}

class A : public base {
public:
    A() {}
    virtual ~A() {}
    virtual void Show()
    {
        std::cout << "A";
    }
    std::ostream& operator<<(std::ostream& os)
    {
        Show();
        return os;
    }

    friend std::ostream& operator<<(std::ostream& os, A& p);
};

std::ostream& operator<<(std::ostream& os, A& p)
{
    p.Show();
    return os;
}

class B : public base {
public:
    B() {}
    virtual ~B() {}

    virtual void Show()
    {
        std::cout << "B";
    }
    friend std::ostream& operator<<(std::ostream& os, B& p);
};

std::ostream& operator<<(std::ostream& os, B& p)
{
    p.Show();
    return os;
}

using MyVariant = std::variant<int, std::string, A, B, base>;

int main()
{
    MyVariant var = "aaaa";
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
        }, var);
    std::cout << std::get<std::string>(var) << std::endl;
    var = A();
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
        }, var);
    std::cout << std::get<A>(var) << std::endl;

    var = base();
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
        }, var);
    std::cout << std::get<base>(var) << std::endl;

    var = B();
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
        }, var);
    std::cout << std::get<B>(var) << std::endl;
    var = 2;
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
        }, var);
    std::cout << std::get<int>(var) << std::endl;
    try
    {
        // std::cout << std::get<float>(var); // 编译失败
        std::cout<< std::get<A>(var); // 此时值是2,取A会抛出异常
    }
    catch (const std::exception& ex)
    {
        std::cout << ex.what() << '\n';
    }
    return 0;
}
文章作者: 张拓
文章链接: http://www.xssl.online/stdvariant/
版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议。转载请注明来自 张拓的博客
浏览次数: 391

张拓

陕西西安蓝田张拓QQ1070410059。一生所求不过“心安”二字。 然,尘世多纷扰。

发表回复