Let's suppose I have a character that can have 1 out of 3 states at a time(crouching, jumping and walking). For each of the 3 states I have a function of type void() that does whatever they are assigned to. I also have an enum that stores the different states and a number for each state.
class Player {
private:
enum State {
crouching = 0,
walking= 1,
jumping = 2
} state;
}
I also have an unordered map that is used to link the different states to their funtions.
class Player {
private:
std::unordered_map<int, void(Player::*)()> stateToFunc;
void playerJump(){ /* code here */ };
void playerCrouch(){ /* code here */ };
void playerWalk(){ /* code here */ };
Player() {
// other stuff
stateToFunc[0] = playerCrouch;
stateToFunc[1] = playerWalk;
stateToFunc[2] = playerJump;
}
I made it so everytime I press a certain key, the state variable will update.
My goal is so on each update I will call only the function stateToFunc[state]
instead of checking manually with a switch statement.
It gives me the following error:
Error C3867 'Player::gActivated': non-standard syntax; use '&' to create a pointer to member
If I use stateToFunc[0] = & playerCrouch;
, it gives me other errors. What can I do to achieve this?
CodePudding user response:
You need to do what the compiler tells you - use the &
operator to get a pointer to a member method. You will also have to specify the class the methods belong to, eg:
class Player {
private:
std::unordered_map<State, void(Player::*)()> stateToFunc;
void playerJump(){ /* code here */ };
void playerCrouch(){ /* code here */ };
void playerWalk(){ /* code here */ };
Player() {
// other stuff
stateToFunc[crouching] = &Player::playerCrouch;
stateToFunc[walking] = &Player::playerWalk;
stateToFunc[jumping] = &Player::playerJump;
}
...
}
Then, to actually call the methods, you can use the ->*
operator, like this:
void Player::doSomething()
{
...
(this->*stateToFunc[state])();
...
}
Alternatively, use std::function
instead, with either std::bind()
or lambdas, eg:
class Player {
private:
std::unordered_map<State, std::function<void()>> stateToFunc;
void playerJump(){ /* code here */ };
void playerCrouch(){ /* code here */ };
void playerWalk(){ /* code here */ };
Player() {
// other stuff
stateToFunc[crouching] = std::bind(&Player::playerCrouch, this);
stateToFunc[walking] = std::bind(&Player::playerWalk, this);
stateToFunc[jumping] = std::bind(&Player::playerJump, this);
// or:
stateToFunc[crouching] = [this](){ playerCrouch(); };
stateToFunc[walking] = [this](){ playerWalk(); };
stateToFunc[jumping] = [this](){ playerJump(); }
}
...
}
void Player::doSomething()
{
...
stateToFunc[state]();
...
}