对于std::variant的二次封装

在 C++17 中,std::variant 提供了一种安全的方式来存储多个可能的类型,它类似于 union,且支持类型安全的操作。此处介绍对std::variant的二次封装,实现智能的赋值与访问。

SmartVariant的代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <variant>
#include <string>

template<typename... Ts>
class SmartVariant {
public:
// 允许用 std::variant<Ts...> 直接初始化
SmartVariant(std::variant<Ts...> var) : innerVar(var) {}

// 允许直接用 Ts... 之一的值初始化
template<typename T>
SmartVariant(T value) : innerVar(value) {}

// 允许 SmartVariant 隐式转换为 Ts... 之一
template<typename T>
operator T() const {
return std::get<T>(innerVar);
}

private:
std::variant<Ts...> innerVar; // 内部存储 std::variant<Ts...>
};

① 允许直接传递 std::variant 进行初始化

SmartVariant(std::variant<Ts...> var) 允许 SmartVariant 直接用 std::variant<Ts...> 进行初始化。例如:

1
2
std::variant<int, double, std::string> v = 42;
SmartVariant<int, double, std::string> sv(v);

此构造函数保证 SmartVariant 可以兼容 std::variant<Ts...>,而不会因为模板构造函数 SmartVariant(T value) 误匹配 std::variant<Ts...> 而导致编译错误。

② 允许使用单个值初始化

此模板构造函数允许 SmartVariant 直接接受 Ts... 之一的值,不需要显式地创建 std::variant<Ts...>SmartVariant 会自动处理赋值。例如:

1
2
SmartVariant<int, double, std::string> sv = 42;       // 存储 int
SmartVariant<int, double, std::string> sv2 = "Hello"; // 存储 string

使用示范

1
2
3
4
5
6
7
8
9
10
11
int main() {
SmartVariant<int, double, std::string> sv = 42;
int x = sv; // 隐式转换为 int
std::cout << "x: " << x << std::endl;

sv = "Hello";
std::string s = sv; // 隐式转换为 string
std::cout << "s: " << s << std::endl;

return 0;
}

运行结果:

1
2
x: 42
s: Hello