Search code examples
c++implicit-conversionpointer-to-memberprivate-inheritance

Pointer to a member function in an inaccessible base


The compilation of the next example :

class A
{
  public:
    void foo()
    {
    }
};

class B : private A
{
  public:
    using A::foo;
};

int main()
{
    typedef void (B::*mf)();
    mf func = &B::foo;

    B b;
    (b.*func)();
}

fails with next errors :

main.cpp||In function ‘int main()’:  
main.cpp|18|error: ‘A’ is an inaccessible base of ‘B’  
main.cpp|18|error:    in pointer to member function conversion

I understand that the A is not accessible base of B, but I am using the using keyword. Shouldn't it allow the access to the function foo?

What are relevant paragraphs in the standard that prevents the above to be compiled?


Solution

  • Access to members of A is governed by chapter 11 "Member Access Control", but pointer-to-member conversions are covered by 4.11. In particular, 4.11/2 states that you can't convert a T A::* to an T B::* when you can't convert an B* to a A*.

    Here's a slight variation of the question:

    class A
    {
      public:
        void foo()
        {
        }
    };
    
    class B : private A
    {
      public:
        using A::foo;
    };
    
    int main()
    {
        typedef void (A::*amf)();
        typedef void (B::*bmf)();
        amf func = &A::foo;
        bmf f2 = static_cast<bmf>(func);
    }
    

    We're still talking about the same function. It's not the name lookup of B::foo that fails (using takes care of that), it's the fact that the type of B::foo is void A::*() which cannot be converted to void B::*().