我试图绕开我的头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
,它只提供了一个operator()
接受 int 作为参数的实现,那就可以了。但是,一旦我尝试为operator()
中的每种类型std::variant
(即此处int
和)实现一个double
,就像在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()
所有类型,然后根据设置方式将它们各自的值接收到bar
正确的类型foo
中?我知道std::get_if<T>()
这在这里可能有用,但理想情况下,除非绝对必要,否则我不想检查每种类型的长 if 语句(这是一个简化的示例,我可能希望在我的std::variant
)。