[ACCEPTED]-Propagating 'typedef' from based to derived class for 'template'-name-lookup

Accepted answer
Score: 49

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.

Score: 43

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

Score: 8

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.

Score: 8

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.

Score: 2

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.

Score: 1

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.

Score: 1

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