Pointers to Members

Member Function Pointers with Templates

Can we use member function pointers with templates to create generic callbacks that work with any class that has a specific method signature?

Abstract art representing computer programming

Yes, we can use member function pointers with templates to create generic callbacks that work with any class having a matching method signature. This is particularly useful for event systems or generic algorithms.

Basic Template Callback

Here’s a basic example using a templated callback function:

#include <iostream>

template <typename T>
class Callback {
public:
  using MemberFunc = void (T::*)();

  Callback(T* Instance, MemberFunc Func) :
    Instance{Instance}, Function{Func} {}

  void Execute() { (Instance->*Function)(); }

private:
  T* Instance;
  MemberFunc Function;
};

class Player {
public:
  void Jump() {
    std::cout << "Player jumped!\n";
  }
};

class Enemy {
public:
  void Jump() {
    std::cout << "Enemy jumped!\n";
  }
};

int main() {
  Player player;
  Enemy enemy;

  Callback playerCallback{
    &player, &Player::Jump};
  Callback enemyCallback{&enemy, &Enemy::Jump};

  playerCallback.Execute();
  enemyCallback.Execute();
}
Player jumped!
Enemy jumped!

Generic Event System

Here's a more advanced example with parameter support:

#include <iostream>
#include <vector>
#include <functional>

template <typename ReturnType, typename... Args>
class EventSystem {
public:
  template <typename T>
  using MemberFunc = ReturnType (T::*)(Args...);

  template <typename T>
  void Subscribe(T* Instance,
                 MemberFunc<T> Func) {
    callbacks.push_back(
      [=](Args... args){
        return (Instance->*Func)(args...);
      });
  }

  void Broadcast(Args... args) {
    for (auto& callback : callbacks) {
      callback(args...);
    }
  }

private:
  std::vector<std::function<ReturnType
    (Args...)>> callbacks;
};

class Player {
public:
  void OnDamage(int Amount) {
    std::cout << "Player took " << Amount <<
      " damage\n";
  }
};

class Enemy {
public:
  void OnDamage(int Amount) {
    std::cout << "Enemy took " << Amount <<
      " damage\n";
  }
};

int main() {
  EventSystem<void, int> damageEvent;

  Player player;
  Enemy enemy;

  damageEvent.Subscribe(&player,
                        &Player::OnDamage);
  damageEvent.Subscribe(&enemy,
                        &Enemy::OnDamage);

  damageEvent.Broadcast(50);
}
Player took 50 damage
Enemy took 50 damage

The benefits of this approach include:

  • Type safety through templates
  • Compile-time checking of method signatures
  • Support for any class with matching method signature
  • No need for inheritance or interfaces
  • Flexibility to add or remove callbacks at runtime

This pattern is commonly used in game engines for event systems, input handling, and component-based architectures.

Answers to questions are automatically generated and may not have been reviewed.

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 125 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved