我正在努力理解std::variant
和std::visit
,并尝试想出一种方法来指定我希望我的变量存储的几种类型(这些类型将进入我的std::variant
),然后通过std::visit
检索存储的数据。考虑以下示例:
#include <iostream>
#include <variant>
#include <string>
struct PrintType {
void operator()(const int &data) {
std::cout << "visiting int node" << std::endl;
}
void operator()(const double &data) {
std::cout << "visiting double node" << std::endl;
}
};
struct SingleOperatorOverload {
int operator()(const int &data) {
std::cout << "visiting int node" << std::endl;
return data;
}
};
struct AllTypesOperatorOverload {
int operator()(const int &data) {
std::cout << "visiting int node" << std::endl;
return data;
}
double operator()(const double &data) {
std::cout << "visiting double node" << std::endl;
return data;
}
};
int main() {
using var_t = std::variant<int, double>;
// print int related operator() content, OK
var_t foo = 42;
std::visit(PrintType(), foo);
// print double related operator() content, OK
foo = 3.1415;
std::visit(PrintType(), foo);
// get value and store into bar, struct with single operator(), OK
foo = 42;
auto bar = std::visit(SingleOperatorOverload(), foo);
std::cout << "bar: " << bar << std::endl;
// get value and store into bar, struct with multiple operator(), ERROR
auto bar = std::visit(AllTypesOperatorOverload(), foo);
std::cout << "bar: " << bar << std::endl;
return 0;
}
这个变量(在这个简化的例子中)可以保存
int
或double
类型。如果我只想基于类型打印一些东西(就像PrintType
结构体中所做的那样),那么它可以正常工作。如果我想通过访问者来检索数据(就像
SingleOperatorOverload
类中所做的那样),该类仅为接受int类型参数的operator()
提供实现,那么这也可以正常工作。然而,一旦我尝试为std::variant
中的每种类型,即int
和double
实现一个operator()
,就像AllTypesOperatorOverload
结构体中一样,就会出现编译错误error: invalid conversion from '...' {aka double ...} to '...' {aka int ...}
,因此似乎std::variant
处理函数签名有所不同?我尝试使用SFINAE但似乎并没有缓解问题。
struct AllTypesOperatorOverload {
template<typename T, std::enable_if_t<std::is_same<T, int>::value>>
T operator()(const T &data) {
std::cout << "visiting int node" << std::endl;
return data;
}
template<typename T, std::enable_if_t<std::is_same<T, double>::value>>
T operator()(const T &data) {
std::cout << "visiting double node" << std::endl;
return data;
}
};
现在将报告一个错误:
error: no type named 'type' in 'struct std::invoke_result<AllTypesOperatorOverload, int&>'
。是否有一种方法可以为所有类型提供operator()
,然后根据foo
的设置方式,接收其相应的值到bar
中,并具有正确的类型?我知道std::get_if<T>()
可能在这里是有用的,但理想情况下,除非绝对必要(这是一个简化的示例,我可能希望在我的std::variant
中有几个更多的类型),否则不想使用长的if语句检查每个类型。
std::variant<int*,std::string>
是否会重现此问题? - Mooing Duck