I'm trying to define base class, which contains typedef's only.
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
private:
Vec_t v; // fails - Vec_t is not recognized
};
Why in B I receive an error that Vec_t is not recognized and I need to write it explicitly?
typename A<T>::Vec_t v;
I believe that this question is duplicate, but I cannot find it now. C++ Standard says that you should fully qualify name according to 14.6.2/3:
In the definition of a class template or a member of a class template, if a base class of the class template 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.
UPD: I found duplicate finally: here it is.
There is something called dependent and nondependent names in case of templates.
If name depends on template parameter T its dependent name and others those do not depend on parameter T are independent names.
Here's the rule: the compiler does not look in dependent base classes (like A) when looking up nondependent names (like Vec_t). As a result, the compiler does not know they even exist let alone are types.
Compiler cannot assume that Vec_t
is a type until it knows T
because There is a potential specialization of A<T>
where A<T>:: Vec_t
is a is a data member
So the solution is use typename
typename A<T>::Vec_t v; ← good
I recommend you go through 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 Vec_t
names a type. For example, A<T>
might be specialized for T=int
to not have that particular typedef
.
For completeness, here's how you could mitigate this nuisance a little, either:
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 useful if you have more than one mentioning of the inherited typedef
in the derived class. Also you don't need to add typename
each time with this.
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