Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 传播';typedef';从'的基于类到派生类;模板&x27;_C++_Templates_Inheritance_Typedef_Name Lookup - Fatal编程技术网

C++ 传播';typedef';从'的基于类到派生类;模板&x27;

C++ 传播';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

我试图定义基类,它只包含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 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;
};