我正在使用gcc 4.6.1使用可变参数模板参数。以下代码按预期编译:
template<typename RetType, typename... ArgTypes>
class Event;
template<typename RetType, typename... ArgTypes>
class Event<RetType(ArgTypes...)>
{
public:
typedef function<RetType(ArgTypes...)> CallbackType;
void emit(ArgTypes...args)
{
for (CallbackType callback : callbacks)
{
callback(args...);
}
}
private:
vector<CallbackType> callbacks;
};
但令我惊讶的是,下面只有一个“Argument Type”的“普通”版本无法编译:
template<typename RetType, typename ArgType>
class Event;
template<typename RetType, typename ArgType>
class Event<RetType(ArgType)> // <- error: wrong number of template arguments (1, should be 2)
{};
g ++ 4.6.1给出了评论中的错误。
有人知道它为什么会导致错误以及如何使它工作?另外,我认为上面的代码是“模板部分专业化”的一种形式吗?
答案 0 :(得分:5)
如果您想制作自己的std::function
版本以获得乐趣,它应该如下所示:
template<class Signature>
class Event;
template<class R, class... Args>
class Event<R(Args...)>{
// ...
};
为什么第一个版本的工作原理已由@ronag解释,参数包(模板参数中为...
)表示 零 或更多< / em>的。如果你想要一个std::
/ boost::function
类似的类(int(int, double, char)
是一个函数类型,我上面给出的代码仍然是正确的签名,这就是为什么它可以适合单个类型声明class Signature
)。
答案 1 :(得分:4)
template<typename RetType, typename ArgType>
class Event;
预计2个模板参数,RetType
和ArgType
,您只需给它一个RetType(ArgType)
。
template<typename RetType, typename... ArgType>
class Event;
预计有一个或多个模板参数,RetType
和可选 ArgType
。
答案 2 :(得分:1)
我认为错误是由于如果模板不是可变参数,那么cpomiler需要标准形式,即类Event<templateArg1, templateArg2>
,这显然不是你提供的。
关于模板专业化:我不同意,如果我没有错,你正在做的是转发类Event
的声明,然后在2行之后有效地声明它。