Accessing protected member functions from test code in C++

sarah picture sarah · Nov 12, 2009 · Viewed 9.1k times · Source

I've been racking my brain trying to think of the best way to access a protected member function from some test code in C++, here's my problem:

//in Foo.h 
Class Foo
{
protected:
    void DoSomething(Data data);
}

//in Blah.h
Class Blah
{
public:
    Foo foo;
    Data data; 
};

//in test code...
Blah blah;
blah.foo.DoSomething(blah.data); // Here's my problem!

Some possible solutions so far:

  • Make the test code class a friend of Foo, but this pollutes Foo with test code
  • Make DoSomething a public function
  • I've looked at creating a test wrapper for Foo, as suggested in this post, however this won't work as Blah contains the instance of Foo.
  • All advice/insight/opinions are most welcome!

    Thanks

    Answer

    Johannes Schaub - litb picture Johannes Schaub - litb · Nov 12, 2009

    There is a way which is completely allowed by the Standard.

    //in Foo.h 
    class Foo
    {
    protected:
        void DoSomething(Data data);
    };
    
    //in Blah.h
    class Blah
    {
    public:
        Foo foo;
        Data data; 
    };
    
    //in test code...
    struct FooExposer : Foo {
      using Foo::DoSomething;
    };
    
    Blah blah;
    (blah.foo.*&FooExposer::DoSomething)(blah.data);
    

    Read the Hidden features of C++ entry for an explanation.


    You may write a macro for your convenience (the parenthesis are there so that you can use this macro also for types that have a comma, like vector<pair<A, B>>):

    #define ACCESS(A, M, N) struct N : get_a1<void A>::type { using get_a1<void A>::type::M; }
    
    template<typename T> struct get_a1;
    template<typename R, typename A1> struct get_a1<R(A1)> { typedef A1 type; };
    

    The matter now becomes

    ACCESS((Foo), DoSomething, GetDoSomething);
    Blah blah;
    (blah.foo.*&GetDoSomething::DoSomething)(blah.data);