类模板 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;
}
本博客所有文章除特别声明外,均采用CC BY-NC-SA 4.0 许可协议。转载请注明来自 张拓的博客!