std::variant
是 C++17 标准库中引入的一个类型安全的联合体(Union)。它允许一个对象在运行时存储多个不同类型中的一种,并且提供了安全访问和类型操作的功能。std::variant
是处理需要存储不同数据类型的场景时的理想选择,比传统的 union
或 void*
更安全、灵活。利用 std::get、std::get_if 和 std::visit,你可以有效地处理不同类型的数据,同时保持代码的清晰和安全。
基本概念
定义语法
#include <variant>
std::variant<Type1, Type2, ..., TypeN> my_variant;
主要特点
- std::variant 提供类型安全的访问机制。使用 std::get 时,如果访问的类型与当前存储的类型不匹配,会抛出异常;使用 std::get_if 则会返回 nullptr,可以安全地检查当前存储的类型。
- std::variant 可能带来一些性能开销,因为它需要在内部管理存储的类型和数据。对于性能敏感的应用,需要谨慎使用,确保性能开销在可接受范围内。
- std::visit 提供了强大的功能来处理存储的不同类型。利用访客模式(Visitor Pattern)可以编写通用代码来处理 std::variant 中的各种类型。
基本用法
#include <iostream>
#include <variant>
#include <string>
// 定义一个 Variant 类型
using MyVariant = std::variant<int, double, std::string>;
int main() {
MyVariant value;
// 存储整数
value = 42;
std::cout << "Integer: " << std::get<int>(value) << std::endl;
// 存储浮点数
value = 3.14;
std::cout << "Double: " << std::get<double>(value) << std::endl;
// 存储字符串
value = "Hello, World!";
std::cout << "String: " << std::get<std::string>(value) << std::endl;
// 使用 visitor 模式
std::visit([](auto&& arg) {
std::cout << "Visitor: " << arg << std::endl;
}, value);
return 0;
}
高级用法
- 嵌套 std::variant, 可以在 std::variant 中嵌套其他 std::variant 或复杂的数据类型。这允许更复杂的数据结构的处理。
#include <iostream>
#include <variant>
#include <string>
using NestedVariant = std::variant<int, std::string>;
using ComplexVariant = std::variant<NestedVariant, double>;
int main() {
ComplexVariant cv = NestedVariant("Nested variant");
std::visit([](const auto& value) {
std::visit([](const auto& inner) {
std::cout << "Inner value: " << inner << std::endl;
}, value);
}, cv);
return 0;
}
自定义实现
- 在 C++ 中实现自定义的 Variant 类,可以利用 C++ 的模板和类型特性来创建一个简化版的 Variant 类。
#include <iostream>
#include <variant>
#include <string>
#include <stdexcept>
class Variant {
public:
// 构造函数
Variant() : data_(nullptr) {}
Variant(int i) : data_(new int(i)) {}
Variant(double d) : data_(new double(d)) {}
Variant(const std::string& s) : data_(new std::string(s)) {}
// 拷贝构造函数
Variant(const Variant& other) {
if (other.data_ == nullptr) {
data_ = nullptr;
} else if (auto pInt = dynamic_cast<int*>(other.data_)) {
data_ = new int(*pInt);
} else if (auto pDouble = dynamic_cast<double*>(other.data_)) {
data_ = new double(*pDouble);
} else if (auto pString = dynamic_cast<std::string*>(other.data_)) {
data_ = new std::string(*pString);
}
}
// 析构函数
~Variant() {
delete data_;
}
// 获取存储的值
template <typename T>
T& get() {
if (auto pValue = dynamic_cast<T*>(data_)) {
return *pValue;
}
throw std::bad_cast();
}
private:
void* data_;
};
int main() {
Variant value(42);
try {
int intValue = value.get<int>();
std::cout << "Integer: " << intValue << std::endl;
} catch (const std::bad_cast& e) {
std::cerr << "Bad cast: " << e.what() << std::endl;
}
return 0;
}