Keyword “typename” in Templates
下面是代码,引用来自Addison Wesley的C++模板:
1 2 3 4 5 | template <typename T> class MyClass { typename T::SubType * ptr; … }; |
Without typename, SubType would be considered a static member. Thus, it would be a concrete variable or object. As a result, the expression
T::SubType *ptr would be a multiplication of the static SubType member of class T with ptr.
现在,当我编译没有关键字"typename"的代码时,我得到的错误是:
编译器是否识别"t"?如果不是,那么它不应该是未定义的引用错误吗?如果是,那么为什么这是一个错误?
好的,这是完整的代码:
1 2 3 4 5 6 7 8 9 10 11 12 | #include <iostream> #include <vector> template <typename T> class MyClass { T::SubType * ptr; }; int main () { return 0; } |
我得到的错误是:
1 2 3 | ~/Desktop/notes **g++ templates/programs/trial.cpp** templates/programs/trial.cpp:6: error: type ‘T’ is not derived from type ‘MyClass<T>’ templates/programs/trial.cpp:6: error: expected ‘;’ before ‘*’ token |
下面是从g++中获得相同错误的另一种方法:
1 2 3 4 5 6 | class Foo { static const int x = 0;}; template <typename T> class MyClass { Foo::x * ptr; }; |
另一个:
1 2 3 4 5 6 | class Foo { static const int x = 0;}; class MyClass { Foo::x * ptr; }; |
但是你会得到一个不同的错误:
1 2 3 4 5 6 | // class Foo { static const int x = 0;}; template <typename T> class MyClass { Foo::x * ptr; }; |
所以:
因为t是一个依赖类型,g++假定
即使
"未定义的引用"是一个链接器错误。由于这段代码甚至无法编译,您不应该期望在任何地方看到"未定义的对t的引用"。
到目前为止,我还不知道
nbsp;
1 2 3 4 5 | class MyClass { class Foo: public MyClass { static const int x = 0;}; Foo::x * ptr; }; |
对于所有这些情况,comeau给出了更合理的错误消息——与派生类型无关,只是说
Without typename, SubType would be considered a static member. Thus, it would be a concrete variable or object. As a result, the expression T::SubType *ptr would be a multiplication of the static SubType member of class T with ptr.
当应用于您给出的示例时,此描述不正确。在类体中不能有表达式,也不能将任何构造解析为乘法。但是,在C++ 03语法中,有一个构造如下
1 2 3 4 | struct Base { int a; }; struct Derived : Base { Base::a; // access-declaration }; |
此结构在C++ 03中被弃用,但仍然支持,并且意味着与以下相同
1 2 3 4 | struct Base { int a; }; struct Derived : Base { using Base::a; // using-declaration }; |
因为您没有告诉编译器
1 2 3 4 5 6 7 | if (! UNIQUELY_DERIVED_FROM_P (IDENTIFIER_TYPE_VALUE (cname), ctype)) { cp_error ("type `%T' is not derived from type `%T'", IDENTIFIER_TYPE_VALUE (cname), ctype); ... } |
当宏显示
1 2 3 | /* Nonzero iff TYPE is uniquely derived from PARENT. Under MI, PARENT can be an ambiguous base class of TYPE, and this macro will be false. */ #define UNIQUELY_DERIVED_FROM_P(PARENT, TYPE) ... |
由于
阅读此处的相关名称:
- 名称绑定和依赖名称(C++)
- 从属名称(向下滚动并阅读本节-如果阅读完整文章,则更好)
编辑:
关于你的问题(你在评论中重复了这个问题):
我认为你发布的不是完整的代码。所以我不能具体评论。此外,有时编译器不够聪明,无法准确地指出模板代码中的错误。因此,我建议您阅读有关从属名称以及何时需要