Petty C++ - std::visit

std::visit通常结合结合前文的Petty C++ - std::variant使用，是 C++ 17 引入的用于处理std::variant中的数据，并执行相应的操作。

基本使用

std::visit需要两个主要参数

visitor：是一个可调用对象（lambda 函数对象），用于处理 variant 中的数据

variants：一个或多个std::variant实例

示例

Copy

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

使用分支

使用多态

Copy
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 和模板类型推导，编译器只会为常见的类型生成特定的逻辑，而通用处理则减少了不必要的代码生