Reputation: 6172
What I want to do : a simple storage class, defined as a template to be as general as possible. And being able to derive from this class another, that would accept anything, convert it to int
(the algorithm is not relevant here), and store it in the underlying class.
But, this doesn't quite work as expected. Here is the minimal test case I wrote:
template<typename T>
class A {
public:
void f(T& foo) { }
};
class B : public A<int> {
public:
template<typename T>
void f(T& foo) { }
};
int main() {
A<int>* ptr = new B;
ptr->f("foo");
delete ptr;
return 0;
}
Of course, this doesn't work:
pierre@raringbeast:~/Workspace/Test/src$ icpc -o Test Test.cpp
Test.cpp(16): error: a reference of type "int &" (not const-qualified) cannot
be initialized with a value of type "const char [4]"
ptr->f("foo");
^
compilation aborted for Test.cpp (code 2)
Is there any way to force the compiler to use the method definition from the B class, or is this a really bad idea?
--
Edit: Made the inheritance public.
Upvotes: 1
Views: 386
Reputation: 171127
First off, as @GermanDiago pointed out, you're using private inheritance, so you're getting the "base class inaccessible" error. Change B
to derive from A<int>
publically.
Even so, this won't fix the issue. Name lookup is based on static types. When you have a pointer to A<int>
, accessing members through that pointer will only look at the members of A<int>
.
You have to access through type B
to see B
's members:
int main() {
B* ptr = new B;
ptr->f("foo");
delete ptr;
return 0;
}
Of course, if I understand your question correctly, this is not what you really want. You might look at the Curiously Recurring Template Pattern instead.
template <class T, class Derived>
class A {
public:
template <class U>
void f(U& bar) {
static_cast<Derived*>(this)->f(bar);
}
void f(T& foo) {
}
};
class B : public A<int, B>
{
public:
template <class T>
void f(T &foo) {
//will be called from A's f(U&)
}
};
int main() {
A<int, B>* ptr = new B;
ptr->f("foo");
delete ptr;
return 0;
}
Of course, this has the downside of B
becoming part of A
's type. I don't think there's a way out of this while still remaining compile-time.
Upvotes: 3
Reputation: 7663
You must use public inheritance:
class B : public A<int> {
//...
}
is-a relationship in c++ is through public inheritance. Private inheritance is what you are currently using.
Upvotes: 1