为什么C ++不能推断模板类型?

时间:2011-08-25 02:52:35

标签: c++ templates visual-c++

为什么编译器无法找出这些模板参数?有没有办法让它这样做?

(我正在使用Visual Studio 2010。)

template<typename T, typename TFunc>
void call(TFunc func) { func(T()); }

void myfunc(void *) { }

int main() { call(myfunc); }

3 个答案:

答案 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_ofboost::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模板来扩展这些内容,以支持多个参数。