Willbur Smith
Willbur Smith

Reputation: 37

How to pass around functions via templates?

Currently trying to implement an event handler for an SDL project. The general idea is that user input events will be handled via Message objects, that will be able to carry around callbacks with different signatures.Currently, what I have is :

#pragma once
#include<functional>

#include"Entity.h"
#include"Enums.h"

typedef std::function<void(void)> VoidCallback;
typedef std::function<void(const Entity& entity)> EntityCallback;

template<typename Functor>
class Message
{
private:
    MessageType message;

public:
    Message(MessageType message, Functor callback) :message(message), callback(callback) {};
    ~Message();
};

However, this arrangement makes it difficult to pass different types of callbacks to different listeners. The current listener implementation is

#include"Message.h"

class Listener
{
public:
    virtual void onNotify(Message<>& event) = 0;
};

which which causes errors. What would be the best way to resolve this issue?

Upvotes: 2

Views: 116

Answers (2)

Joseph Franciscus
Joseph Franciscus

Reputation: 371

You cannot have a template virtual function

Can a C++ class member function template be virtual?

#include "Message.h"

class Listener
{
public:

    //you may use a template function as such
    template<class func>
    void onNotify(Message<func>& event) { /*must implement*/ }

    //or specialize for specific function calls
    virtual void onNotify(Message<some_known_func>& even) = 0;
};

If you want to utilize template-methods with a virtual-like features you may be interested in looking into CRTP. (CRTP enables the super-class to call the subclasses methods)

Upvotes: 1

Xaqq
Xaqq

Reputation: 4386

It is not possible for a virtual function to be templated.

Virtual function are called through a vtable, which is basically an array of function pointer. Each virtual method in a base class takes up a slot in the virtual table. Obviously the virtual table size needs to be known at compile time, because it is part of the object definition.

class Base {
public:
    virtual void hello(){};
    virtual void bye(){};   
}

The vtable could look like this:

  • Pointer to hello.
  • Pointer to bye.

So the vtable needs 2 functions pointer.

Now if either hello() or bye() were to be templated, how could we create a vtable?

  • Pointer to hello<int>()
  • Pointer to hello<char>().

We cannot know in advance all the variation of the templated function so it's not possible to build a vtable.

Upvotes: 1

Related Questions