可变参数模板函数接受lambda [英] Variadic template function accepting lambda

查看:122
本文介绍了可变参数模板函数接受lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解下面的代码所引起的编译器错误。我有一个可变参数的模板函数,该函数接受具有指定类型的lambda
,并且尝试调用该函数会导致模板由于不匹配而被视为无效候选。

  #include< functional> 

template< typename ... ResultTypes>
void executeWithResultHandler(std :: function< void(ResultTypes ...)> lambda)
{
}

int main(int argc,char ** argv)
{
executeWithResultHandler< int>([[(int arg){
});;
返回0;
}

这会导致以下错误:

  $ c ++ -std = c ++ 11 reduction.cpp 
reduction.cpp:10:5:错误:没有匹配的函数可以调用'executeWithResultHandler'
executeWithResultHandler< int>([[](int arg){
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~
reduction.cpp:4:6:注意:候选模板被忽略:无法将'function< void(int,type-parameter-0-0 ...)>'与
'< lambda cpp:10:3​​5>'
void executeWithResultHandler(std :: function< void(ResultTypes ...)> lambda)
^
产生1个错误。

如果我将声明更改为可变参数:

  template< typename ResultType> 
void executeWithResultHandler(std :: function< void(ResultType)> lambda)
{
}

然后适用于上面的玩具示例,但是对于真正的问题,我需要任意参数ts。
这里是否有我想念的东西,或者完成此目的的另一种方式?



编辑:这被错误地标记为重复项,我相信-欺骗无法回答我所问的问题。这个问题专门与这里的 variadic template 问题有关:请注意,当我将模板切换为非variadic时,lambda会按预期正确地转换为std :: function类型。不管参数有多少,都是如此,只要不以可变方式处理即可。



但是,有效


解决方案

可变参数模板的问题在于编译器不知道您明确指定的 int 是否为 ResultTypes ... 选择> complete 列表,因此它尝试从您提供的参数中推断出可选的剩余参数,这显然失败了。这是可变参数模板参数的常见陷阱,并不限于lambda。



解决方案始终意味着您从编译器中删除了此选项,例如

  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));
}


I'm trying to understand the compiler error that I'm getting fo the code below. I've got a variadic template function which accepts a lambda with the specified types, and attempting to call that function results in the template not being considered a valid candidate due to a mismatch.

#include <functional>

template<typename ... ResultTypes>
void executeWithResultHandler(std::function<void (ResultTypes...)> lambda)
{
}

int main(int argc, char **argv)
{
    executeWithResultHandler<int>([] (int arg) {
    });
    return 0;
}

This results in the following error:

$ 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.

If I change the declaration to not be variadic:

template<typename ResultType>
void executeWithResultHandler(std::function<void (ResultType)> lambda)
{
}

then it works for the toy example above, but for the real problem I need arbitrary arguments. Is there something I’m missing here, or anther way to accomplish this?

EDIT: This was marked as a duplicate incorrectly, I believe- the dupe does not answer the question I'm asking. This question specifically has to do with the variadic template issue here: Please note that, when I switch the template to be non-variadic the lambda converts to the std::function type correctly, as expected. This is true regardless of the number of arguments, as long as that is not handled in a variadic fashion.

However, it does not work with the variadic version specifically, despite an expectation that the parameter pack is unpacked to a set of real parameters, and the explicit specification of the template parameter list at the function call site.

解决方案

The problem with variadic templates in your case is that the compiler does not know whether the int you explicitly specified is the complete list for ResultTypes... or not, so it tries to deduce the optional remaining arguments from the parameter you gave it, and that obviously fails. This is a common pitfall with variadic template arguments and it is not limited to lambdas.

A solution always implies that you take away this option from the compiler, e.g.

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));
}

这篇关于可变参数模板函数接受lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆