c++ – Accessing class members via .* and ->*

Question:

When are the x.*ptm or p->*ptm ? Please provide a minimal example where this may be needed. And in general, where it can really come in handy. Is it worth using them? Is it possible to replace them with something?

Answer:

You have to call methods in this way exactly if you have saved a pointer to this method 🙂 @Harry described how it works, but why is a good question.

Often a situation arises when programmers want to simplify their lives (the lazy ones). For example, you wrote the following code:

#include <iostream>

enum class State {
    One, Two, Three
};

class A {
    State _cur_state;
public:
    A(State s) : _cur_state(s) {}

    void DoSomething() {
        switch (_cur_state) {
            case State::One:
                std::cout << "Foo" << std::endl;
                break;
            case State::Two:
                std::cout << "Bar" << std::endl;
                break;
            case State::Three:
                std::cout << "Baz" << std::endl;
                break;
        }    
    };
};

int main() {
    A(State::One).DoSomething();
}

After a while, the realization will come that it is easier to write

class A {
    State _cur_state;
public:
    A(State s) : _cur_state(s) {}

    void DoSomething() {
        static std::unordered_map<State, std::string> state_to_string {
            { State::One, "Foo" },
            { State::Two, "Bar" },
            { State::Three, "Baz" }
        };

        std::cout << state_to_string[_cur_state] << std::endl;       
    };    
};

After a while, it turns out that there must be some tricky code in case ah, and you return to the original version by moving this code to methods:

class A {
    State _cur_state;

    void DoFoo() { /* code */ }
    void DoBar() { /* code */ }
    void DoBaz() { /* code */ }
public:
    A(State s) : _cur_state(s) {}

    void DoSomething() {
        switch (_cur_state) {
            case State::One:
                DoFoo();
                break;
            case State::Two:
                DoBar();
                break;
            case State::Three:
                DoBaz();
                break;
        }        
    };    
};

But then you remember about pointers to methods and the code becomes clean again!

class A {
    State _cur_state;

    void DoFoo() { /* code */ }
    void DoBar() { /* code */ }
    void DoBaz() { /* code */ }
public:
    A(State s) : _cur_state(s) {}

    void DoSomething() {
        static std::unordered_map<State, void(A::*)()> state_to_method {
            { State::One, &A::DoFoo },
            { State::Two, &A::DoBar },
            { State::Three, &A::DoBaz }
        };

        (this->*state_to_method[_cur_state])();
    };    
};

PS I did not write error handling.

PPS In the case of enum s, the vector version or the original one will be faster , but this example is for academic purposes.

Scroll to Top