C++ 传播';typedef';从'的基于类到派生类;模板&x27;
我试图定义基类,它只包含typedefC++ 传播';typedef';从'的基于类到派生类;模板&x27;,c++,templates,inheritance,typedef,name-lookup,C++,Templates,Inheritance,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 }; 模板 甲级 { 公众: typedef s
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
};
模板
甲级
{
公众:
typedef std::向量向量;
};
模板
B类:公共A
{
私人:
Vec\u t v;//失败-无法识别Vec\u t
};
为什么在B中,我收到一个无法识别向量的错误,我需要显式地写入它
typename A<T>::Vec_t v;
typename A::Vec\u t v;
因为编译器不确定Vec\t
是否命名类型。例如,A
可能专门用于T=int
而没有特定的typedef您需要明确限定Vec\u T
的使用,因为编译器不知道Vec\u T
来自何处
由于类模板A可能是专门化的,因此它不能假设A的结构。专门化可能包括一个不是typedef的Vec\u t
,或者它甚至可能根本不包括一个成员Vec\u t
。Vec\u t不是一个依赖名,编译器需要知道它是什么,而不需要实例化任何模板(在这种情况下是基类)。这与:
template <class T>
class X
{
std::string s;
}
模板
X类
{
std::字符串s;
}
在这里,即使没有实例化X,编译器也需要了解std::string,因为名称不依赖于模板参数T(在编译器可以假定的范围内)
总而言之,模板基类中的typedef对于在派生类中使用似乎毫无用处。然而,typedef对用户很有用 对于模板,有一种称为依赖名和非依赖名
如果名称依赖于模板参数T,则其依赖名称和其他不依赖于参数T的名称是独立名称
规则是:编译器不会
查看依赖基类(如
A) 在查找非依赖项时
名称(如Vec_t)。因此,
编译器甚至不知道它们
存在,更不用说类型了
编译器在知道t
之前不能假定Vec\u t
是一个类型,因为a
有一个潜在的专门化,其中a::Vec\u t
是一个数据成员
因此,解决方案是使用typename
typename A<T>::Vec_t v; ← good
typename A::Vec\u t v;← 好的
我建议你经历一下
旧链接:我相信这个问题是重复的,但我现在找不到。C++标准称,您应该完全按照14.62/2的名称限定:
在类模板或类模板成员的定义中,如果类模板的基类依赖于模板参数,在类模板或成员的定义点或类模板或成员的实例化过程中,未在非限定名称查找期间检查基类作用域
UPD:我终于找到了副本:。这个概念可能与我们如何使用std::vector
有关。例如,如果我们有一个std::vector Foo
。现在,我们决定使用它的任何成员类型,比如说迭代器。在这个场景中,我们明确提到
std::vector<int>::iterator foo_iterator;
为了完整起见,以下是您可以稍微缓解这种麻烦的方法:
- 在派生类中重新定义这些类型,或者更好—与
方法-
- 只需使用声明将这些名称导入派生类范围中的
:
模板
甲级
{
公众:
typedef std::向量向量;
};
模板
B类:公共A
{
公众:
使用typename A::Vec\t;
// .........
私人:
矢量电视;
};
如果您在派生类中不止一次提到继承的typedef
,那么它会很有用。同样,你也不需要每次都添加typename
。完全重复:好吧,实际上不是完全重复,因为你提到的帖子谈论的是一种方法,而这篇文章谈论的是一种类型。typename a::Vec_t v;很好。不需要这样,我总是担心我必须“重新定义”一切。。。这很不愉快,一点也不愉快。顺便说一句,你不需要所有的模板参数和所有的,在限定的时候。由于注入的类名,只需编写typename B::Vec_t
@johanneschaub litb我正试图按照您所说的那样做,但如果我没有为B指定模板参数,我就会出错。(B不是类、命名空间或枚举)@gonzalosorla我得到了与您相同的错误结果,但只是在我的一个平台上,一个旧的C++标准。我想知道完全限定的需要是否在某一点上发生了变化?你的意思是classx:T{
吗?对于T
类型变量,a
只是向前声明,它没有定义。只有a
其中T
是类型(不是类型变量)可以定义(通过专门化模板定义或显式专门化)IOW,即使您从C++中移除模板显式和部分特化(并且不更改任何其他),它仍然是不正确的。您的答案似乎是除了解释之外提供解决方案的唯一答案。谢谢。如果您通知我您已更正了链接,我将为您提供+1。您有一个输入错误。使用typename a::Vec_t;
应该是使用typename a::Vec_t;
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
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;
};