4

I currently write on an event handler system in C++0x. The "handlers" for each event (there can be multiple handlers) are registered by passing any kind of function/method that can be stored in a std::function object. This is done in C# style using the overloaded += operator. My Event-Class looks basically like this (stripped for better readability):

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

Now I have another internal method for retrieving the actual function pointer from the std::function objects stored in the vector. It basically tries to do something like this:

// Preceeding: Get an iterator 'it' from the vector
HandlerFunctionPtr pt2func = it->target<HandlerSignature>();

At this point, when I use the Event class in my application, the compilation failes. Using a GCC 4.7 build I get the following error messages for the line above:

error: expected primary-expression before '>' token
error: expected primary-expression before ')' token

I've tested a little bit with the target<>() Method and the following works perfectly, assuming that the return type is void and there's one argument of type int:

typedef void(Signature)(int);
typedef void(*FunctionPtr)(int);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();

But as soon as there is one template argument involved, I get the above posted errors:

typedef THandlerReturn(Signature)(int);
typedef THandlerReturn(*FunctionPtr)(void);
std::function<Signature> func;
FunctionPtr pt2func = func.target<Signature>();

Can anyone tell me why that actually is, and if yes, if there's any way to make it work? Any help and insights are very appreciated! Thanks in advance!

PuerNoctis
  • 1,364
  • 1
  • 15
  • 34

1 Answers1

5

You need to use template keyword as:

HandlerFunctionPtr pt2func = it->template target<HandlerSignature>();

Its because you're calling a function template on an object whose type depends on a template argument. In the absence of the keyword template, the compiler is going to parse your code as,

HandlerFunctionPtr pt2func = ( (it->target) < HandlerSignature ) >();

which makes absolutely no sense. Hence the error.


To know this in detail as to why template is needed, read this excellent explanation by @Johannes Schaub:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851