为什么编译器无法找出这些模板参数?有没有办法让它这样做?
(我正在使用Visual Studio 2010。)
template<typename T, typename TFunc>
void call(TFunc func) { func(T()); }
void myfunc(void *) { }
int main() { call(myfunc); }
答案 0 :(得分:11)
T
在参数列表中没有出现,因此无法从函数参数推断出T
。要推导的所有类型必须出现在参数列表中的推导上下文中。例如,
template <typename TReturn, typename TParameter>
void call(TReturn (*f)(TParameter))
{
f(TParameter());
}
答案 1 :(得分:3)
函数模板的模板参数推导仅适用于函数参数,没有别的。从来没有为确定模板参数而查看函数定义,因此无法推导出参数T
。
您可以通过将类型合并到函数签名中来解决您的情况:由于您希望使用函数本身调用外部函数,因此请明确说明:
template <typename T> void foo(void(*f)(T))
{
T x;
f(x);
// ...
}
答案 2 :(得分:2)
将函数重载与仿函数结合起来,在一般情况下,确定哪些参数可以传递给可调用实体是不可能的。
考虑一下,例如
struct FunctorExample {
void operator()(int x) {...}
std::string operator()(const std::string& ) {...}
};
如果有某种方法可以让编译器对参数进行模式匹配,那么在应用于FunctorExample
时,它必须具有未定义或错误行为。
相反,趋势似乎是当您想要使用仿函数模板元程序时,您可以指定仿函数和参数列表。示例(在我的头顶)是boost::result_of
和boost::fusion
。
编辑:那就是说,如果你愿意在某种程度上限制你的注意力,并且你可以使用一些C ++ 11语法(decltype
),你可以安排内省更多:
// Support functors with a very simple operator():
template <typename T> struct argument :
public argument<decltype(&T::operator())> {};
// Pointers to member functions
template <typename C, typename R, typename A> struct argument<R(C::*)(A)>
{typedef A type;};
// Function types
template <typename R, typename A> struct argument<R(A)> {typedef A type;};
// Function pointer types.
template <typename R, typename A> struct argument<R(*)(A)> {typedef A type;};
// Now for call:
template <typename FuncType>
void call(FuncType func) {
typedef typename argument<FuncType>::type Arg;
func(Arg());
}
// example:
class FunctorInt {public: int operator()(int ) {return 0;};};
void myfunc(void *) {}
int main() {
call(myfunc);
call(FunctorInt());
}
可以使用Variadic模板来扩展这些内容,以支持多个参数。