C++ 将“typedef”从“模板”的基类传播到派生类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1643035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Propagating 'typedef' from based to derived class for 'template'
提问by dimba
I'm trying to define base class, which contains typedef's only.
我正在尝试定义仅包含 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
};
Why in B I receive an error that Vec_t is not recognized and I need to write it explicitly?
为什么在 BI 中会收到无法识别 Vec_t 的错误,我需要明确地编写它?
typename A<T>::Vec_t v;
采纳答案by Kirill V. Lyadvinsky
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:
我相信这个问题是重复的,但我现在找不到了。C++ 标准说你应该根据 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 lookupeither 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.
UPD:我终于找到了重复的:在这里。
回答by Xinus
There is something called dependent and nondependentnames in case of templates.
在模板的情况下,有一种叫做依赖和非依赖名称的东西。
If name depends on template parameter T its dependentname and others those do not depend on parameter T are independentnames.
如果名称依赖于模板参数 T,则其依赖名称和其他不依赖于参数 T 的名称是独立名称。
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.
这是规则:在查找非依赖名称(如 Vec_t)时,编译器不会查找依赖基类(如 A)。结果,编译器甚至不知道它们存在,更不用说是类型了。
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
编译器Vec_t
在知道之前不能假设它是一种类型,T
因为有一个潜在的特化,A<T>
其中A<T>:: Vec_t
a 是数据成员
So the solution is use typename
所以解决方案是使用 typename
typename A<T>::Vec_t v; ← good
I recommend you go through this https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types.
我建议您浏览此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
旧(损坏)链接:http: //www.parashift.com/c++-faq-lite/templates.html#faq-35.18
回答by Jesse Beder
Because the compiler's not certain that Vec_t
names a type. For example, A<T>
might be specialized for T=int
to nothave that particular typedef
.
因为编译器不确定Vec_t
命名类型。例如,A<T>
可能是专门用于T=int
给不具有特定的typedef
。
回答by Roman Kruglov
For completeness, here's how you could mitigate this nuisance a little, either:
为了完整起见,您可以通过以下方法稍微减轻这种麻烦:
- re-typedef those types in derived classes, or better - as with methods -
- just import those names in the derived class scope with a
using declaration
:
- 在派生类中重新定义这些类型,或者更好 - 与方法一样 -
- 只需在派生类范围内导入这些名称
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.
如果您不止一次提到typedef
派生类中的继承,这会很有用。你也不需要typename
每次都添加这个。
回答by user200783
You need to explicitly qualify the use of Vec_t
because the compiler does not know where Vec_t
comes from.
您需要明确限定使用,Vec_t
因为编译器不知道Vec_t
来自哪里。
It cannot assume anything about the structure of A, since the class template A may be specialized. The specialization may include a Vec_t
which is not a typedef, or it may not even include a member Vec_t
at all.
它不能假设任何关于 A 的结构,因为类模板 A 可能是特化的。专业化可能包含一个Vec_t
不是 typedef 的 a,或者它甚至可能根本不包含一个成员Vec_t
。
回答by UncleBens
Vec_t is not a dependent name, and the compiler needs to know what it is without instantiating any templates (base class in this case). It is really no different from:
Vec_t 不是依赖名称,编译器需要知道它是什么,而无需实例化任何模板(在本例中为基类)。它与以下内容没有什么不同:
template <class T>
class X
{
std::string s;
}
Here as well the compiler needs to know about std::string even if X is not instantiated, since the name does not depend on the template argument T (as far as the compiler can assume).
即使 X 没有实例化,编译器也需要知道 std::string ,因为名称不依赖于模板参数 T (就编译器可以假设而言)。
All in all, typedefs in a template base class seem rather useless for use in derived class. The typedefs are useful for the user, however.
总而言之,模板基类中的 typedef 在派生类中似乎毫无用处。然而,typedef 对用户很有用。
回答by RAD
This concept can be associated with how we use std::vector<T>
. For example, if we have a std::vector<int> Foo
. Now, we decide to use any of it's member types, lets say an iterator
. In this scenario we explicitly mention
这个概念可以与我们如何使用std::vector<T>
. 例如,如果我们有一个std::vector<int> Foo
. 现在,我们决定使用它的任何成员类型,比如说一个iterator
. 在这种情况下,我们明确提到
std::vector<int>::iterator foo_iterator;
Similarly in your case, in order to use a public member type Vec_t
of template <typename T> class A
, you need to explicitly declare it as
同样,在你的情况下,为了使用公共成员类型Vec_t
的template <typename T> class A
,你需要明确地声明为
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;