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.
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
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!
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 pointersthis
must ensure object lifetimeThe choice between these approaches depends on your specific needs:
std::function
for maximum flexibilityAnswers to questions are automatically generated and may not have been reviewed.
Learn how to create pointers to class functions and data members, and how to use them