std::visit
通常结合结合前文的Petty C++ - std::variant
使用,是 C++ 17 引入的用于处理std::variant
中的数据,并执行相应的操作。
基本使用#
std::visit
需要两个主要参数
-
visitor:是一个可调用对象(lambda 函数对象),用于处理 variant 中的数据
-
variants:一个或多个
std::variant
实例
示例#
int main() {
// 创建一个 std::variant,它可以存储 int 或 std::string
std::variant<int, std::string> var;
// 将一个 int 值存入 variant
var = 42;
// 使用 std::visit 来处理 variant 中的值
std::visit([](auto&& arg) {
std::cout << "Value: " << arg << std::endl;
}, var);
// 将一个 std::string 值存入 variant
var = std::string("Hello, world!");
// 再次使用 std::visit 来处理新的值
std::visit([](auto&& arg) {
std::cout << "Value: " << arg << std::endl;
}, var);
return 0;
}
多个 variant#
处理多个 variant 时,需要 visitor 能够处理所有可能出现的类型,如果不在 visitor 中对不同类型的组合进行分支处理,visitor 会为每一种可能的类型组合生成不同的函数调用逻辑。如果有多个 variant,每个 variant 包含多种类型,可能的类型组合呈指数增长。
为了避免这种情况,可以使用如下方法节省开销:
- 减少 variant 的类型数量
- 使用
std::monostate
// todo - 使用分支
- 使用多态
template<typename T>
void process(const T& value) {
if constexpr (std::is_same_v<T, int>) {
std::cout << "Processing int: " << value << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "Processing string: " << value << std::endl;
} else {
std::cout << "Processing other type" << std::endl;
}
}
通过 if constexpr 和模板类型推导,编译器只会为常见的类型生成特定的逻辑,而通用处理则减少了不必要的代码生