Why I can not simply use types defined in base class if both classes are templates? Is there some rule about searching of template members? Here is the simplest example I could deduce:
struct iA {
using type = int;
};
template <class T> struct tA {
using type = T;
};
struct iB1 : iA {
void f(type i) {}
};
struct iB2 : tA<int> {
void f(type i) {}
};
template <class T> struct tB1 : iA {
void f(type i) {}
};
template <class T> struct tB2 : tA<int> {
void f(type i) {}
};
template <class T> struct tB3 : tA<T> {
// void f(type i) {} // error: 'type' has not been declared
void f(typename tA<T>::type i) {}
};
int main() {}
Of course, I can just add typename tA<T>::
, but is there a more elegant solution?
A derived class can have only one direct base class.
An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template. is a template used to generate template classes.
Class Templates like function templates, class templates are useful when a class defines something that is independent of the data type. Can be useful for classes like LinkedList, BinaryTree, Stack, Queue, Array, etc. Following is a simple example of a template Array class.
Deriving from a non-template base classIt is quite possible to have a template class inherit from a 'normal' class. This mechanism is recommended if your template class has a lot of non-template attributes and operations. Instead of putting them in the template class, put them into a non-template base class.
The problem is that the base class is dependent, and thus its scope is only examined when we are looking up dependent names. [temp.dep]/3:
In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
The reason for this rule is that there might be e.g. specializations of the base class template. Since we don't know the specific template arguments at definition time, we cannot inspect the base classes scope.
type
isn't dependent and thus will not be looked up in the dependent base tA<T>
. However, because it isn't dependent, a declaration for it must be available at definition time, [temp.res]/10:
If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.
If you need to use type
frequently in the derived class, using
declarations can help.
template <class T> struct tB3 : tA<T> {
using typename tA<T>::type;
void f(type i) {}
};
Demo.
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