H Xu
H Xu

Reputation: 305

Function type in template doesn't compile

I was playing with variadic template parameters using gcc 4.6.1. The following code compiles as expected:

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;
};

But to my suprise the following "normal" version that has only one "Argument Type" doesn't compile:

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 gives error as in the comment.

Anybody knows why it causes the error and how to make it work? Also, am I right in thinking the above code is a form of "template partial specialisation"?

Upvotes: 5

Views: 305

Answers (3)

Xeo
Xeo

Reputation: 131789

If you want to make your own version of std::function for fun, it should look like this:

template<class Signature>
class Event;

template<class R, class... Args>
class Event<R(Args...)>{
  // ...
};

Why your first version works is already explained by @ronag, a parameter pack (... in template parameter) means zero or more. The code I gave above is still the correct signature if you want a std::/boost::function-like class (int(int, double, char) is a function type, that's why it can fit into a single type declaration like class Signature).

Upvotes: 5

ronag
ronag

Reputation: 51255

template<typename RetType, typename ArgType>
class Event;

Expects 2 template arguments, RetType and ArgType, you only give it one RetType(ArgType).

template<typename RetType, typename... ArgType>
class Event;

Expects 1 or more template arguments, RetType and optional ArgTypes.

Upvotes: 4

Lorenzo Pistone
Lorenzo Pistone

Reputation: 5188

I think that the error is due to the fact that if the template is not variadic, then the cpomiler expects the standard form, that is class Event<templateArg1, templateArg2>, which is clearly not what you're feeding it with.

About the template specialization: I disagree, if I'm not wrong what you're doing there is to forward the declaration of the class Event, then effectively declare it just 2 lines later.

Upvotes: 1

Related Questions