使用 std::visit 处理 std::variant
std::visit 是 C++17 提供的一种高效工具,用于操作 std::variant 中存储的不同类型数据。它允许我们为每种可能的类型定义不同的行为,而无需显式地进行类型检查。以下是一些常见的用法示例。
通过类对象实现访问
可以通过定义一个包含多个重载 operator() 的结构体或类来处理不同类型的变体数据。
示例代码:
#include <iostream>
#include <variant>
#include <string>
struct VariantHandler {
void operator()(double value) const {
std::cout << "Double: " << value << '\n';
}
void operator()(int value) const {
std::cout << "Integer: " << value << '\n';
}
void operator()(const std::string& value) const {
std::cout << "String: " << value << '\n';
}
};
int main() {
std::variant<int, double, std::string> data1(42), data2(3.14), data3("Example");
std::visit(VariantHandler(), data1);
std::visit(VariantHandler(), data2);
std::visit(VariantHandler(), data3);
return 0;
}
使用泛型 Lambda 表达式简化代码
如果只需要对所有类型执行相似的操作,可以使用泛型 Lambda 表达式以减少代码冗余。
示例代码:
#include <iostream>
#include <variant>
#include <string>
auto displayValue = [](const auto& value) {
std::cout << "Value: " << value << '\n';
};
int main() {
std::variant<int, double, std::string> data1(42), data2(3.14), data3("Lambda");
std::visit(displayValue, data1);
std::visit(displayValue, data2);
std::visit(displayValue, data3);
return 0;
}
结合重载机制处理多种类型
当需要针对每种类型提供不同的逻辑时,可以使用模板和重载技术创建一组 Lambda 函数。
示例代码:
#include <iostream>
#include <variant>
#include <string>
template<typename... Args>
struct MultiHandler : Args... {
using Args::operator()...;
};
template<typename... Args>
MultiHandler(Args...) -> MultiHandler<Args...>;
int main() {
std::variant<int, std::string> item(42);
std::visit(MultiHandler{
[](int num) { std::cout << "Number: " << num << '\n'; },
[](const std::string& text) { std::cout << "Text: " << text << '\n'; }
}, item);
return 0;
}
同时处理多个 std::variant
std::visit 支持同时操作多个变体,这在涉及多类型组合的情况下非常有用。
示例代码:
#include <iostream>
#include <variant>
#include <string>
struct SmallObject {};
struct LargeObject {};
int main() {
std::variant<SmallObject, LargeObject> objectA, objectB;
std::visit(MultiHandler{
[](SmallObject&, SmallObject&) { std::cout << "Both are small\n"; },
[](SmallObject&, LargeObject&) { std::cout << "One small, one large\n"; },
[](LargeObject&, SmallObject&) { std::cout << "One large, one small\n"; },
[](LargeObject&, LargeObject&) { std::cout << "Both are large\n"; }
}, objectA, objectB);
return 0;
}