使用传递的 lambda 调用 std::visit
Call std::visit with passed lambdas
我有一个包含 variant
.
的结构
我想为该结构编写一个成员函数,它应该 运行 根据当前持有的类型变体进行编码。
但是,我在编译时遇到了问题。
我不想使用更多的“模板恶作剧”,比如使用单独的结构来定义 operator(T&)
,因为它会更加污染语法。
这是一个例子:
struct Data {
std::variant<int, double> var;
//Into this function,multiple lambdas should be passed for cases that the user wants to handle
template<typename ... Funcs>
void apply(Funcs&&... funcs) {
std::visit(std::forward<Funcs>(funcs)...,var);
}
};
int main() {
Data d;
d.var = 4;
//variant holds int and lambda provided that takes int&, execute it:
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
d.var = 0.0;
//variant holds double but no lambda passed that takes a double, hence nothing happens:
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
}
我什至不知道编译器想要我做什么:
https://godbolt.org/z/oM4584anf
您的问题是 std::visit()
需要一个必须处理 每个 类型的 std::variant
.
的“访问者”
However, I have issues making it compile. I don't want to use more "template shenanigans" like using a separate struct to define operator(T&) since it pollutes the syntax even more.
没什么复杂的。
您可以简单地添加一个简单的结构(带推导指南)如下(并按照 cppreference std::visit()
page 中的建议)
template<class... Ts> struct overloaded : Ts...
{ using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
然后,假设您想要 std::visit()
return void
,您可以在 apply()
方法中添加一个通用的什么都不做的 lambda
template<typename ... Funcs>
void apply(Funcs&&... funcs) {
std::visit(overloaded{ // <-- pass through overloaded
[](auto const &){}, // <-- and add this generic lambda
std::forward<Funcs>(funcs)...},var);
}
现在第一个apply()
电话
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
应该编译调用提供的 lambda,因为它是一个更好的匹配(假定 d
包含一个 int
),并且第二次调用编译调用不执行任何操作的通用 lambda,因为通用 lambda 是更好地匹配 double
.
我有一个包含 variant
.
我想为该结构编写一个成员函数,它应该 运行 根据当前持有的类型变体进行编码。
但是,我在编译时遇到了问题。
我不想使用更多的“模板恶作剧”,比如使用单独的结构来定义 operator(T&)
,因为它会更加污染语法。
这是一个例子:
struct Data {
std::variant<int, double> var;
//Into this function,multiple lambdas should be passed for cases that the user wants to handle
template<typename ... Funcs>
void apply(Funcs&&... funcs) {
std::visit(std::forward<Funcs>(funcs)...,var);
}
};
int main() {
Data d;
d.var = 4;
//variant holds int and lambda provided that takes int&, execute it:
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
d.var = 0.0;
//variant holds double but no lambda passed that takes a double, hence nothing happens:
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
}
我什至不知道编译器想要我做什么: https://godbolt.org/z/oM4584anf
您的问题是 std::visit()
需要一个必须处理 每个 类型的 std::variant
.
However, I have issues making it compile. I don't want to use more "template shenanigans" like using a separate struct to define operator(T&) since it pollutes the syntax even more.
没什么复杂的。
您可以简单地添加一个简单的结构(带推导指南)如下(并按照 cppreference std::visit()
page 中的建议)
template<class... Ts> struct overloaded : Ts...
{ using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
然后,假设您想要 std::visit()
return void
,您可以在 apply()
方法中添加一个通用的什么都不做的 lambda
template<typename ... Funcs>
void apply(Funcs&&... funcs) {
std::visit(overloaded{ // <-- pass through overloaded
[](auto const &){}, // <-- and add this generic lambda
std::forward<Funcs>(funcs)...},var);
}
现在第一个apply()
电话
d.apply([](int& i){
std::cout << "I am Int Poggers" << std::endl;
});
应该编译调用提供的 lambda,因为它是一个更好的匹配(假定 d
包含一个 int
),并且第二次调用编译调用不执行任何操作的通用 lambda,因为通用 lambda 是更好地匹配 double
.