Luke B.
Luke B.

Reputation: 1288

Inheriting from class with a template parameter friend

I'm trying to do the following: I have a class and whenever I declare a new instance of this class I want to set a static variable in another class. I'm trying to do it with templates so I can do something like class C : public D<AA, BB, CC, DD> (using variadic parameters). The problem is that the static variable of the classes AA, BB, CC, DD (all which share the same base) is protected. So I'm trying make C a friend of the classes so it can access the variable.

What I tried is this:

template <class T>
class Foo
{
    protected:
    static T* t;
    friend T;
};
template <class T>
T* Foo<T>::t = nullptr;

First I declared the base class Foo, which has the static variable and the friend declaration. This is meant to be inherited by other classes.

Then I made this:

template <class Self, class T> //T = Type derived from Foo
struct Bar
{
    Bar()
    {
        T::t = static_cast<Self*>(this);
    }
};

Which is the class that when instantiated will set the static variable in the type T.

And this is the final implementation:

struct FooDerived;

struct BarDerived : public Bar<BarDerived, FooDerived>
{

};

struct FooDerived : public Foo<BarDerived>
{

};

My idea is that:

  1. BarDerived will set the static t in FooDerived
  2. FooDerived inherits Foo<BarDerived> which is a friend of BarDerived
  3. Since BarDerived is a friend of Foo<BarDerived>, it can access Foo<BarDerived>::t

But that doesn't work and I get the following compile error:

prog.cpp: In instantiation of ‘void Bar<Self, T>::test() [with Self = BarDerived; T = FooDerived]’:
prog.cpp:37:9:   required from here
prog.cpp:11:4: error: ‘BarDerived* Foo<BarDerived>::t’ is protected
 T* Foo<T>::t = nullptr;
    ^
prog.cpp:18:8: error: within this context
   T::t = static_cast<Self*>(this);
        ^

(https://ideone.com/jcRcH0)

Did I miss something with the way I expected the templates/friendship to behave?

Upvotes: 0

Views: 60

Answers (1)

Jarod42
Jarod42

Reputation: 217775

You may use the following: https://ideone.com/RW3xfV

template <class T>
class Foo
{
protected:
    static T* t;
    template <class Self, class U> //T = Type derived from Foo
    friend struct Bar;
};

as it is Bar which requires access to Foo<T>::t.

Upvotes: 1

Related Questions