我正在尝试创建一个函数,该函数接受可变数量的任何类型的参数,但是即使我所做的简单示例也遇到了错误
#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");
答案 0 :(得分:2)
一个简单的建议:以可推断的类型名而不是std::function
的形式接收可调用对象
我的意思是(还添加了完美的转发功能)
template <typename F, typename ... Ts>
void callFunction(F const & func, Ts && ... pars)
{ func(std::forward<Ts>(pars)...); }
很明显,在不进行任何说明的情况下调用它
callFunction(&myFunc, "Hello world");
这是避免将可调用对象转换为std::function
的额外优势。
无论如何,我在您的代码中看到两个问题:
1)如果您以std::function
的形式接收函数,并且以相同类型的参数列表的形式接收参数类型列表(在这种情况下为可变列表,但对这个问题并不重要),您必须确保两个列表中的类型完全匹配 。
这不是您的情况,因为该函数接收到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
。
因此,编译器无法从Ts...
推断出&myFunc
类型列表,因为它不是std::function
,也无法将&myFunc
转换为{{1 }},因为它不知道std::function
类型列表。
我看到您已经在Ts...
列表中说明了 first 类型,但这还不够,因为Ts...
列表是一个可变的列表,因此编译器不会这样做。不知道Ts...
列表中只有一种类型。
此问题的一个简单解决方案是将函数作为简单的Ts...
类型推导。
否则,如果您用两个模板类型列表编写了F
,则可以将callFunction()
传递给函数
std::function
但我认为这不是令人满意的解决方案。