我目前在C ++ 0x中的事件处理程序系统上编写。通过传递可以存储在std::function
对象中的任何类型的函数/方法来注册每个事件的“处理程序”(可以有多个处理程序)。这是使用重载的+ =运算符以C#样式完成的。我的事件类基本上看起来像这样(剥离以获得更好的可读性):
template<typename THandlerReturn, typename THandlerArgs...>
class Event {
public:
typedef THandlerReturn(HandlerSignature)(THandlerArgs...);
typedef THandlerReturn(*HandlerFuntionPtr)(THandlerArgs...);
typedef typename std::function<HandlerSignature> HandlerFunction;
void operator += (HandlerFunction handler) {
_handlers.push_back(handler);
}
// Some other methods for calling all handlers, ctors, etc.
private:
std::vector<HandlerFunction> _handlers;
};
现在我有另一个内部方法从存储在向量中的std::function
对象中检索实际的函数指针。它基本上试图做这样的事情:
// Preceeding: Get an iterator 'it' from the vector
HandlerFunctionPtr pt2func = it->target<HandlerSignature>();
此时,当我在我的应用程序中使用Event类时,编译失败了。使用GCC 4.7版本我得到以上行的以下错误消息:
error: expected primary-expression before '>' token
error: expected primary-expression before ')' token
我已经使用target<>()
方法进行了一些测试,并且以下工作完美,假设返回类型为void
并且有一个类型为int
的参数:
typedef void(Signature)(int);
typedef void(*FunctionPtr)(int);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();
但是只要涉及一个模板参数,我就会得到上面发布的错误:
typedef THandlerReturn(Signature)(int);
typedef THandlerReturn(*FunctionPtr)(void);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();
任何人都可以告诉我为什么会这样,如果是的话,是否有任何方法可以使其发挥作用?任何帮助和见解都非常感谢!提前谢谢!
答案 0 :(得分:5)
您需要使用template
关键字:
HandlerFunctionPtr pt2func = it->template target<HandlerSignature>();
这是因为你在类型依赖于模板参数的对象上调用函数模板。如果没有关键字template
,编译器将把您的代码解析为
HandlerFunctionPtr pt2func = ( (it->target) < HandlerSignature ) >();
这绝对没有意义。因此错误。
要详细了解为什么需要template
,请阅读 @Johannes Schaub 的优秀解释: