可变模板函数接受lambda
Variadic template function accepting lambda
我试图理解编译器错误,我得到下面的代码。我有一个可变的模板函数,它接受一个lambda使用指定的类型,并且尝试调用该函数将导致模板由于不匹配而不被视为有效的候选模板。
#include <functional>
template<typename ... ResultTypes>
void executeWithResultHandler(std::function<void (ResultTypes...)> lambda)
{
}
int main(int argc, char **argv)
{
executeWithResultHandler<int>([] (int arg) {
});
return 0;
}
这会导致以下错误:
$ c++ -std=c++11 reduction.cpp
reduction.cpp:10:5: error: no matching function for call to 'executeWithResultHandler'
executeWithResultHandler<int>([] (int arg) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
reduction.cpp:4:6: note: candidate template ignored: could not match 'function<void (int, type-parameter-0-0...)>' against
'<lambda at reduction.cpp:10:35>'
void executeWithResultHandler(std::function<void (ResultTypes...)> lambda)
^
1 error generated.
如果我改变声明为非可变的:
template<typename ResultType>
void executeWithResultHandler(std::function<void (ResultType)> lambda)
{
}
则适用于上面的玩具示例,但对于实际问题,我需要任意参数。我在这里是否遗漏了什么,或者有其他方法可以完成这个任务?
编辑:我认为这篇文章被错误地标记为副本——被复制的人没有回答我的问题。这个问题特别与可变变量模板问题有关:请注意,当我将模板切换为非可变变量时,lambda会像预期的那样正确地转换为std::函数类型。无论参数有多少,只要不是以可变的方式处理,这都是正确的。
然而,尽管期望参数包被解压缩为一组实际参数,并且在函数调用处明确规范了模板参数列表,却不能专门用于可变版本。
在您的情况下,可变模板的问题是编译器不知道您显式指定的int
是否为ResultTypes...
的完整列表,因此它试图从您给它的参数中推断可选的剩余参数,这显然失败了。这是可变模板参数的一个常见缺陷,不仅限于lambdas。
一个解决方案总是暗示你从编译器中拿走这个选项,例如
template<typename ... ResultTypes>
void executeWithResultHandler_impl(std::function<void (ResultTypes...)> lambda)
{
}
template<typename ... ResultTypes, typename F>
void executeWithResultHandler(F&& lambda)
{
executeWithResultHandler_impl(std::function<void (ResultTypes...)>(lambda));
}
我之前链接的重复问题准确地解释了你的情况。
一个std::function
是不是一个lambda,它是一种容器类型,可以存储任何类型的可调用的对象。您可以将lambda分配给std::function
,但在这种情况下,必要的转换由std::function
构造函数执行。
在你的例子中
template<typename ... ResultTypes>
void executeWithResultHandler(std::function<void (ResultTypes...)> lambda)
{}
executeWithResultHandler<int>([](int arg){});
编译器无法从上面的lambda表达式推断参数包ResultTypes
中的类型。模板实参推导需要精确匹配,不考虑隐式转换,并且这里涉及的类型,如前所述,是完全不同的。
如果我改变声明为不可变的,那么它就可以工作了
template<typename ResultType>
void executeWithResultHandler(std::function<void (ResultType)> lambda)
{}
executeWithResultHandler<int>([](int arg){});
这样做是因为不再涉及模板参数推导。executeWithResultHandler
只接受一个模板形参,您已经显式地指定了这个形参,并且由于lambda隐式地可转换为std::function
,因此重载解析将找到一个匹配的。
请注意,在第一种情况下,除了int
之外,可能还有更多的模板参数,您没有显式指定。
通过显式地将lambda转换为std::function
,可以使原始示例正常工作。
executeWithResultHandler<int>(std::function<void(int)>([] (int arg) {}));
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 如何建立使用模板函数的lambda函数的尾部返回类型
- 我可以将调用类的"this"传递给 lambda 函数吗?
- 两组使用lambda函数的大括号
- 尝试将lambda函数放在队列中时出现一般分配器错误(可能是与unique_ptr有关的错误)
- 我可以在这里替换什么,因为我不能在 C# 中使用隐式变量的 lambda 函数?
- 为什么我不能在 constexpr lambda 函数中使用 std::tuple
- C++:Lambda 函数指针转换的用例是什么?
- 将 lambda 函数作为参数传递C++
- 如何将 lambda 函数作为参数发送到另一个函数
- 传递 lambda 函数的权衡是什么?
- 如何使用类模拟 C++11 中的 lambda 函数和闭包?
- 不是 lambda 函数中的常量表达式
- 如何使用可变参数数重载 lambda 函数?
- 如何通过指针传递lambda函数?
- 使用带有 lambda 函数指针的模板
- openmp c++ 中并行块内 lambda 函数的奇怪行为
- C++ 中 Lambda 函数中的溢出
- 将数组传递到 lambda 函数中
- lambda 函数未显示正确的结果