Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Access protected members from templated (static) member function

Tags:

c++

templates

Ok so I'm taking a sort of modified CRTP route here to avoid virtual function look-ups. But I just can't understand one error it gives me...

So I'm trying to translate:

class A
{
public:
    static void foo(A *pA)
    {
        pA->bar();
    }

protected:
    virtual void bar()
    {
        TRACE0(_T("A::bar\n"));
    }
};

class B : public A
{
protected:
    virtual void bar()
    {
        TRACE0(_T("B::bar\n"));
    }
};

which works as expected to:

class A
{
public:
    template <class T>
    static void foo(T *pT)
    {
        pT->bar();
    }

protected:
    void bar()
    {
        TRACE0(_T("A::bar\n"));
    }
};

class B : public A
{
protected:
    void bar()
    {
        TRACE0(_T("B::bar\n"));
    }
};

which gives the error:

error C2248: 'B::bar' : cannot access protected member declared in class 'B'
see declaration of 'B::bar'
see declaration of 'B'
see reference to function template instantiation 'void A::foo<B>(T *)' 
being compiled with
[
    T=B
]

Now I know, this is easily fixed by adding friend class A; to class B, but that's not very neat. Isn't there another way?

EDIT: Example usage:

B b;
b.foo<B>(&b);

EDIT #2: The member function foo being static doesn't matter I noticed.

like image 647
demorge Avatar asked Jan 27 '12 20:01

demorge


1 Answers

In the first case bar is virtual function and foo accesses it through a pointer to A thus invoking the function pointer and the specified index of Vtable as layout'ed by class A. Thus it works.

However, in second case, A::foo explicitly calls the non-virtual function from different class it has no access to. B::bar is not a virtual overload of A::bar - it is completely different unrelated function.

Therefore, making friend class A; is the neatest you can get, I am afraid.

like image 112
Krizz Avatar answered Oct 06 '22 20:10

Krizz