I am trying to implement a CRTP hierarchy of classes. I am interested in the base class to have access to the data member of a derived class down the chain:
#include <iostream>
template <class Derived>
class A {
public:
void showv() {
std::cout << static_cast<const Derived*>(this)->v << std::endl;
}
};
template <class Derived>
class B : public A< Derived > {
typedef A<Derived> base;
friend base;
};
class fromA : public A<fromA> {
typedef A<fromA> base;
friend base;
protected:
int v = 1;
};
class fromB : public B<fromB>
{
typedef B<fromB> base;
friend base;
protected:
int v = 2;
};
int main()
{
// This runs ok
fromA derived_from_a;
derived_from_a.showv();
// Why doesn't the following compile and complains about the protected member?
fromB derived_from_b;
derived_from_b.showv();
return 0;
}
Although the first derived class (fromA) compiles and runs as expected, the second (fromB), that derives from a class derived fromA, doesn't.
- What is the reason the friend declarations are not channeled through?
- Any suggestions on a workaround?
The issue is: the friend of my friend is not my friend.
In
fromAyou haveWhich makes
A<fromA>a friend andshowcan accessfromA's protected member.In
fromByou also haveBut this doesn't make
Aa friend, it makesByour friend. Even though A is a friend ofBit does not mean it is also now a friend offromBand this is why you cannot accessvinshow.One way you can fix this is to make
typedef A<Derived> base;public or protected inBand then infromByou can addfriend base::base;which would giveAaccess.