Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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"?

like image 757
H Xu Avatar asked Dec 29 '11 11:12

H Xu


People also ask

Can templates be used for functions?

Templates are powerful features of C++ which allows us to write generic programs. We can create a single function to work with different data types by using a template.

Are templates compile time?

The use of templates can be thought of as compile-time polymorphism. The technique is used by a number of languages, the best-known being C++, but also Curl, D, Nim, and XL.

What does template <> mean?

A template is a form, mold or pattern used as a guide to make something.

How do you declare a template function?

To instantiate a template function explicitly, follow the template keyword by a declaration (not definition) for the function, with the function identifier followed by the template arguments. template float twice<float>( float original ); Template arguments may be omitted when the compiler can infer them.


3 Answers

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).

like image 81
Xeo Avatar answered Oct 13 '22 18:10

Xeo


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.

like image 41
ronag Avatar answered Oct 13 '22 18:10

ronag


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.

like image 30
Lorenzo Pistone Avatar answered Oct 13 '22 18:10

Lorenzo Pistone