[ACCEPTED]-Propagating 'typedef' from based to derived class for 'template'-name-lookup
I believe that this question is duplicate, but 10 I cannot find it now. C++ Standard says 9 that you should fully qualify name according 8 to 14.6.2/3:
In the definition of a class 7 template or a member of a class template, if 6 a base class of the class template depends 5 on a template-parameter, the base class scope is not examined during unqualified name lookup either at 4 the point of definition of the class template 3 or member or during an instantiation of 2 the class template or member.
UPD: I found duplicate 1 finally: here it is.
There is something called dependent and 13 nondependent names in case of templates.
If name depends 12 on template parameter T its dependent name and others 11 those do not depend on parameter T are independent names.
Here's 10 the rule: the compiler does not look in 9 dependent base classes (like A) when looking 8 up nondependent names (like Vec_t). As 7 a result, the compiler does not know they 6 even exist let alone are types.
Compiler 5 cannot assume that Vec_t
is a type until it knows 4 T
because There is a potential specialization 3 of A<T>
where A<T>:: Vec_t
is a is a data member
So the solution 2 is use typename
typename A<T>::Vec_t v; ← good
I recommend you go through 1 this https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types.
Old (broken) link: http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
Because the compiler's not certain that 2 Vec_t
names a type. For example, A<T>
might be specialized 1 for T=int
to not have that particular typedef
.
For completeness, here's how you could mitigate 4 this nuisance a little, either:
- re-typedef those types in derived classes, or better - as with methods -
- just import those names in the derived class scope with a
using declaration
:
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
public:
using typename A<T>::Vec_t;
// .........
private:
Vec_t v;
};
It can be 3 useful if you have more than one mentioning 2 of the inherited typedef
in the derived class. Also 1 you don't need to add typename
each time with this.
You need to explicitly qualify the use of 6 Vec_t
because the compiler does not know where 5 Vec_t
comes from.
It cannot assume anything about 4 the structure of A, since the class template 3 A may be specialized. The specialization 2 may include a Vec_t
which is not a typedef, or 1 it may not even include a member Vec_t
at all.
Vec_t is not a dependent name, and the compiler 10 needs to know what it is without instantiating 9 any templates (base class in this case). It 8 is really no different from:
template <class T>
class X
{
std::string s;
}
Here as well 7 the compiler needs to know about std::string 6 even if X is not instantiated, since the 5 name does not depend on the template argument 4 T (as far as the compiler can assume).
All 3 in all, typedefs in a template base class 2 seem rather useless for use in derived class. The 1 typedefs are useful for the user, however.
This concept can be associated with how 6 we use std::vector<T>
. For example, if we have a std::vector<int> Foo
. Now, we 5 decide to use any of it's member types, lets 4 say an iterator
. In this scenario we explicitly 3 mention
std::vector<int>::iterator foo_iterator;
Similarly in your case, in order 2 to use a public member type Vec_t
of template <typename T> class A
, you need 1 to explicitly declare it as
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.