70

我正在尝试定义仅包含 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
};

为什么在 BI 中收到 Vec_t 无法识别的错误,我需要显式编写它?

typename A<T>::Vec_t v;
4

7 回答 7

46

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

在类模板或类模板成员的定义中,如果类模板的基类依赖于模板参数,则在非限定名称查找期间不会在类的定义点检查基类范围模板或成员,或在类模板或成员的实例化期间。

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

于 2009-10-29T11:54:30.877 回答
43

在模板的情况下,有一些称为依赖和非依赖名称的东西。

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

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

编译器在知道之前不能假定它Vec_t是一个类型,T因为存在一个潜在的特殊化,A<T>A<T>:: Vec_ta 是一个数据成员

所以解决方案是使用 typename

 typename A<T>::Vec_t v;  ← good

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

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

于 2009-10-29T11:49:09.397 回答
8

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

于 2009-10-29T11:38:38.353 回答
7

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

  • re-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;
};

typedef如果您在派生类中不止一次提到继承,它会很有用。你也不需要typename每次都添加这个。

于 2018-09-19T16:47:42.510 回答
2

您需要明确限定使用 of,Vec_t因为编译器不知道Vec_t来自哪里。

它不能假设任何关于 A 的结构,因为类模板 A 可能是特化的。特化可能包括Vec_t不是 typedef 的 a,或者它甚至可能根本不包括成员Vec_t

于 2009-10-29T11:40:21.797 回答
1

Vec_t 不是依赖名称,编译器需要知道它是什么而不实例化任何模板(在本例中为基类)。真的和以下没有什么不同:

template <class T>
class X
{
    std::string s;
}

即使 X 没有实例化,编译器也需要知道 std::string ,因为名称不依赖于模板参数 T (就编译器可以假设而言)。

总而言之,模板基类中的 typedef 在派生类中使用似乎毫无用处。然而,typedef 对用户很有用。

于 2009-10-29T11:44:13.157 回答
1

这个概念可能与我们如何使用std::vector<T>. 例如,如果我们有一个std::vector<int> Foo. 现在,我们决定使用它的任何成员类型,比如说一个iterator. 在这种情况下,我们明确提到

std::vector<int>::iterator foo_iterator;

同样,在您的情况下,为了使用 的公共成员类型Vec_ttemplate <typename T> class A您需要将其显式声明为

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
于 2018-02-21T17:01:59.973 回答