Search code examples
c++pointersencapsulationmemberpointer-to-member

How to call the value of a function-pointer member of a nested class of some enclosing class from within another nested class?


This is a pretty convoluted question, but I've tried to simplify the code as much as possible from my actual codebase. Let's say I have some class T with nested classes S and M. I have some methods method1 and method2 of S, and I also have a pointer selectedMethod that points to one selected of the two methods, by default method1.

class T
{
    class S
    {
        T &t;

        double method1(std::vector <double> params);
        double method2(std::vector <double> params);

        double (S::*selectedMethod)(std::vector <double>) = &S::method1;
    }

    class M
    {
        T &t;

        double method3(std::vector <double> vec);
    }

    S s;
    M m;
}

As shown, I store the instance of T that the instances of S and M, s and m respectively, correspond to using the pointers t.

Next, let's say that I'd like to call whichever method selectedMethod points to within some method method3 of M. Why is it that this has to be done with:

double T::M::method3(std::vector <double> vec){

    double ret = (&t.s->*t.s.selectedMethod)(vec);

    return ret;
}

instead of simply

double T::M::method3(std::vector <double> vec){

    double ret = (*t.s.selectedMethod)(vec);

    return ret;
}

? To me the prefix &t.s-> seems redundant.


Solution

  • To me the prefix &t.s-> seems redundant

    It only seems that way because you store the pointer to member inside the same object on which you invoke the member. But given the general case

    auto foo_ptr = &SomeClass::foo;
    SomeClass obj;
    
    (obj*.foo_ptr)();
    

    Both parts of the syntax are required. One obviously denotes the member, while the other denotes that object that is being accessed.

    In your special case the object may "appear" twice, but the two ends of the expression still denote different things. On the right hand side t.s.selectedMethod still only designates the pointer. The compiler is not obliged to examine the expression and divine the object from it.