繁体   English   中英

带参数包的功能对象出现“模板参数推导/替换失败”错误

[英]“template argument deduction/substitution failed” error with function object with parameter pack

我正在尝试制作一个函数,该函数需要可变数量的任何类型的参数,但是即使我所做的简单示例也遇到了错误

#include <iostream>
#include <functional>

template<class... Ts>
void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
{
    function(parameters...);
}

void myFunc(const std::string& output)
{
    std::cout << output << std::endl;
}

int main() 
{
    callFunction<const std::string&>(&myFunc, "Hello world");
    return 0;
}

当我在Ideone中运行以上代码时, 出现此错误:

prog.cpp: In function ‘int main()’:
prog.cpp:17:57: error: no matching function for call to ‘callFunction(void (*)(const string&), const char [12])’
  callFunction<const std::string&>(&myFunc, "Hello world");
                                                         ^
prog.cpp:5:6: note: candidate: template<class ... Ts> void callFunction(const std::function<void(Ts ...)>&, Ts ...)
 void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
      ^~~~~~~~~~~~
prog.cpp:5:6: note:   template argument deduction/substitution failed:
prog.cpp:17:57: note:   mismatched types ‘const std::function<void(Ts ...)>’ and ‘void (*)(const string&) {aka void (*)(const std::__cxx11::basic_string<char>&)}’
  callFunction<const std::string&>(&myFunc, "Hello world");

一个简单的建议:以可推断的类型名而不是std::function接收可调用对象

我的意思是(还添加了完美的转发功能)

template <typename F, typename ... Ts>
void callFunction(F const & func, Ts && ... pars)
 { func(std::forward<Ts>(pars)...); }

并且,显然,在不进行任何说明的情况下调用它

callFunction(&myFunc, "Hello world");

这是避免将callable转换为std::function的额外优势。

无论如何,我在您的代码中看到两个问题:

1)如果您收到的函数作为std::function接收相同类型的参数列表的ot参数类型列表(在这种情况下为可变列表,但对这个问题并不重要),则必须确保两个列表中的类型完全匹配。

这不是您的情况,因为该函数接收std::string const &并且您将一个字符串文字"Hello world"作为一个参数传递给它作为参数,而char const [12]是另一种类型。

当推导类型时,这会导致编译错误,因为编译器无法在两种类型之间进行选择。

您可以解决接收两种类型的列表

template <typename ... Ts1, typename Ts2>
void callFunction (std::function<void(Ts1...)> const & function,
                   Ts2 && ... parameters)
 { function(std::forward<Ts2>(parameters)...); }

但是现在我们有第二个问题

2)您传递了一个指针函数( &myFunc ),其中callFunction()等待std::function

我们有一个鸡蛋问题,因为&myFunc可以转换为std::function但不是std::function

因此,编译器无法从&myFunc推断类型的Ts...列表,因为它不是std::function ,也无法将&myFunc转换为std::function因为它不知道Ts...类型列表。

我看到您已经说明了Ts...列表中的第一个类型,但还不够,因为Ts...列表是一个可变的,因此编译器不知道Ts...只有一个类型Ts...清单。

解决此问题的简单方法是将函数作为简单的F类型传递。

否则,如果您编写了带有两个模板类型列表的callFunction() ,则可以将std::function传递给该函数

std::function<void(std::string const &)>  f{&myFunc};

callFunction(f, "Hello world");

但我认为这不是令人满意的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM