It seems that a protected member from a template policy class is inaccessible, even with a class hierarchy which seems correct.
For instance, with the following code snippet :
#include <iostream>
using namespace std;
template <class T>
class A {
protected:
T value;
T getValue() { return value; }
public:
A(T value) { this->value = value; }
};
template <class T, template <class U> class A>
class B : protected A<T> {
public:
B() : A<T>(0) { /* Fake value */ }
void print(A<T>& input) {
cout << input.getValue() << endl;
}
};
int main(int argc, char *argv[]) {
B<int, A> b;
A<int> a(42);
b.print(a);
}
The compiler (clang on OS X, but gcc returns the same type of error) returns the following error :
Untitled.cpp:18:21: error: 'getValue' is a protected member of 'A<int>'
cout << input.getValue() << endl;
^
Untitled.cpp:25:5: note: in instantiation of member function 'B<int, A>::print' requested here
b.print(a);
^
Untitled.cpp:8:7: note: can only access this member on an object of type 'B<int, A>'
T getValue() { return value; }
^
1 error generated.
The strange thing is that the last note from the compiler is totally correct but already applied since the b
object is of type 'B<int, A>'
. Is that a compiler bug or is there a problem in the code ?
Thanks
You have misunderstood the meaning of protected access.
Protected members are callable by derived classes. But only on the base object contained inside the class itself.
For example, if i simplify the problem, using :
class A {
protected:
void getValue(){}
};
class B : protected A
{
public:
void print(A& input)
{
input.getValue(); //Invallid
}
};
getValue cannot be called on a "A" object other than the "A" object inside the class itself. This for example is valid.
void print()
{
getValue(); //Valid, calling the base class getValue()
}
As pointed out by Dan Nissenbaum and shakurov. This is however also valid:
void print(B& input)
{
input.getValue();
}
This is because we explicitly say that input is a object of B. And the compiler know that all that objects of B has protected access to getValue. In the case when we pass a A&, the object might as-well be a type of C, wich could be derrived from A with private access.
Let's forget for a minute about the template and look at this:
class A {
protected:
int value;
int getValue() { return value; }
public:
A(int value) { this->value = value; }
};
class B : protected A {
public:
B() : A(0) { /* Fake value */ }
void print(A& input) {
cout << input.getValue() << endl;
}
};
The print()
method's implementation is wrong because you can't access non-public member of A
inside B
. And here's why: from within B
, you can only access non-public members of B
. Those members may be either inherited or not — it doesn't matter.
On the other hand, A& input
may not be a reference to an instance of B
. It may be a reference to another subclass (which may well have getValue()
inaccessible).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With