将'typedef'从基于'模板'的派生类传播

dim*_*mba 61 c++ inheritance templates typedef name-lookup

我正在尝试定义基类,它只包含typedef.

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
};
Run Code Online (Sandbox Code Playgroud)

BI中为什么会收到Vec_t无法识别的错误,我需要明确写出来?

typename A<T>::Vec_t v;
Run Code Online (Sandbox Code Playgroud)

Kir*_*sky 44

我相信这个问题是重复的,但我现在找不到它.C++标准说你应该根据14.6.2/3完全限定名称:

在类模板的定义或类模板的成员中,如果类模板的基类依赖于模板参数,则在的定义时,在非限定名称查找期间不会检查基类作用域.模板或成员或在类模板或成员的实例化期间.

UPD:我终于找到了重复:这里是.

  • 顺便说一句,总是让我感到烦恼的是我不得不"重新定义"所有东西......这不是令人愉快的,也不是令人愉快的. (24认同)
  • 顺便说一句,你不需要所有模板参数和所有模板参数.由于注入了类名,只需编写`typename B :: Vec_t`即可 (14认同)

Xin*_*nus 37

在模板的情况下,存在称为依赖和依赖名称的东西.

如果name依赖于模板参数T,其依赖名称和其他不依赖于参数T的名称是独立名称.

这是规则:在查找非依赖名称(如Vec_t)时,编译器不会查找依赖的基类(如A).结果,编译器不知道它们甚至存在,更不用说类型了.

编译器不能假设它Vec_t是一个类型,直到它知道,T因为有一个潜在的专业化,A<T>其中A<T>:: Vec_ta是一个数据成员

所以解决方案是使用typename

 typename A<T>::Vec_t v;  ? good
Run Code Online (Sandbox Code Playgroud)

我建议你浏览这个https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types.

旧(破碎)链接:http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18


Jes*_*der 8

因为编译器不确定Vec_t命名类型.例如,A<T>可能是专门用于T=int具有特定的typedef.


Rom*_*lov 5

为了完整起见,以下是您可以减轻这种麻烦的方法之一:

  • 在派生类中重新typedef那些类型,或者更好-与方法一样-
  • 只需使用以下命令将这些名称导入派生类范围中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;
};
Run Code Online (Sandbox Code Playgroud)

如果typedef在派生类中对继承项的提及不止一个,它可能会很有用。另外,您不需要typename每次都添加此内容。