Lambda Member Function Pointers

Is it possible to create a member function pointer to a lambda that's stored as a class member?

While you can't create a direct member function pointer to a lambda, there are several ways to achieve similar functionality. There are three possible approaches below.

Using std::function

Here, we use the std::function wrapper:

#include <functional>
#include <iostream>

class Character {
public:
  Character() {
    // Initialize lambda member
    Attack = [this](int Damage){
      Health -= Damage;
      std::cout << "Took " << Damage <<
        " damage. Health: " << Health << '\n';
    };
  }

  void TakeDamage(int Amount) {
    Attack(Amount);
  }

private:
  int Health{100};
  std::function<void(int)> Attack;
};

int main() {
  Character player;
  player.TakeDamage(30);
  player.TakeDamage(20);
}
Took 30 damage. Health: 70
Took 20 damage. Health: 50

Using Template Member

We can set this up using a template member as follows:

#include <functional>
#include <iostream>

class Character {
public:
  template <typename F>
  void SetAttackBehavior(F&& Lambda) {
    Attack = std::forward<F>(Lambda);
  }

  template <typename... Args>
  void ExecuteAttack(Args&&... args) {
    Attack(std::forward<Args>(args)...);
  }

private:
  std::function<void(int)> Attack = [](int){
    std::cout << "No attack behavior set\n";
  };
};

int main() {
  Character player;

  // Default behavior
  player.ExecuteAttack(10);

  // Set new behavior
  player.SetAttackBehavior(
    [](int Damage){
      std::cout << "Dealing " << Damage <<
        " damage!\n";
    });

  player.ExecuteAttack(20);
}
No attack behavior set
Dealing 20 damage!

Using Variant Pattern

Here's another example where we provide a SetAttackMethod() allowing external code to switch behaviors:

#include <functional>
#include <iostream>

class Character {
public:
  enum class AttackType { Melee, Ranged };

  void SetAttackType(AttackType Type) {
    switch (Type) {
    case AttackType::Melee:
      CurrentAttack = [this](int Damage){
        std::cout << "Melee attack: " << Damage
          << '\n';
      };
      break;
    case AttackType::Ranged:
      CurrentAttack = [this](int Damage){
        std::cout << "Ranged attack: " << Damage
          << '\n';
      };
      break;
    }
  }

  void Attack(int Damage) {
    CurrentAttack(Damage);
  }

private:
  std::function<void(int)> CurrentAttack
    = [](int){
      std::cout << "No attack set\n";
    };
};

int main() {
  Character player;

  player.Attack(10);

  player.SetAttackType(
    Character::AttackType::Melee);
  player.Attack(20);

  player.SetAttackType(
    Character::AttackType::Ranged);
  player.Attack(30);
}
No attack set
Melee attack: 20
Ranged attack: 30

Key considerations:

  • std::function has more overhead than raw member function pointers
  • Lambdas capturing this must ensure object lifetime
  • Template approach can be more efficient but less flexible
  • Consider using type erasure for complex scenarios
  • Be careful with circular references in captures
  • Lambda storage may increase object size

The choice between these approaches depends on your specific needs:

  • Use std::function for maximum flexibility
  • Use templates for better performance
  • Use variant pattern for structured behavior switching
  • Consider combining approaches for complex systems

Pointers to Members

Learn how to create pointers to class functions and data members, and how to use them

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Member Function Pointers vs Virtual Functions
Why would we use member function pointers instead of virtual functions when we want to change behavior at runtime?
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?
Member Function Pointer Performance
How do member function pointers impact performance compared to virtual functions or std::function? Are there memory overhead considerations?
Async Member Function Pointers
How can we use member function pointers with asynchronous operations like std::async or thread pools?
Serializing Member Function Pointers
What's the best way to serialize/deserialize member function pointers for saving game state or network communication?
Smart Pointers with Member Functions
How can we use member function pointers with smart pointers (shared_ptr, unique_ptr) effectively?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant