c++templatesvariadic-templatesvariadic-functions

c++ completely generic event dispatcher


I try again to explain better again what I would achieve.
I would like make a thing like this (inspired to Unity's UnityEvent):

Public "variables" declared in some classes:

GameEvent<> OnEnemySpawn = GameEvent<>();
GameEvent<string> OnPlayerSpawn = GameEvent<string>(); 
GameEvent<string, float> OnEnemyDie = GameEvent<string, float>();

Referral where some other classes subscribe their methods:

...
enemySpawner.OnEnemySpawn.Subscribe(IncreaseEnemyAliveCountByOne);
...
playerSpawner.OnPlayerSpawn.Subscribe(NewPlayerSpawned);
...
enemy.OnEnemyDie.Subscribe(IncreasePlayerScore);
...
// Subscribed methods declaration
void IncreaseEnemyAliceCountByOne() { ... }
void NewPlayerSpawned(string playerName) { ... }
void IncreasePlayerScore(string playerName, float scoreToAdd) { ... }

And then GameEvent class would be able to notify the event happens:

...
OnEnemySpawn.Notify();
...
OnPlayerSpawn.Notify(newPlayer.PlayerName);
...
OnEnemyDie.Notify(playerKiller.PlayerName, scoreOnKill);
...

Actually, I achieved the declaration and subscription part creating this class:

templace<class ... T>
class GameEvent
{
private:
    std::vector<std::function<void(T...)>> _subscribers;

public:
    void Subscribe(std::function<void(T...)> newSubscriber)
  {
    _subscribers.push_back(newSubscriber);
  }
}

The thing that makes me crazy is how implement the Notify method. How should I know how many parameters I received and which types they have

void Notify(T...)
{
    for (std::function<void(T...)> subscriber : _subscribers)
  {
    
  }
}

I hope now this is a valid question cause I'm losing my mind behind this


Solution

  • What is wrong with the obvious way?

    void Notify(T... args)
    {
        // note: no need to write the type if it's quite long
        // note: & means the std::function isn't copied
        for (auto const& subscriber : _subscribers)
        {
            subscriber(args...);
        }
    }