When is the “typename” keyword necessary?
Possible Duplicate:
Officially, what is typename for?
Where and why do I have to put the template and typename keywords?
考虑下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 | template<class K> class C { struct P {}; vector<p> vec; void f(); }; template<class K> void C<K>::f() { typename vector<p> ::iterator p = vec.begin(); } |
为什么"类型".在这个例子中,有必要吗?是否有任何其他的情况下,必须指定的"类型"?
简短回答:每当引用依赖名称的嵌套名称时,即嵌套在具有未知参数的模板实例中。
答案是:C++中有三层实体:值、类型和模板。所有这些都可以有名称,而单独的名称并不能告诉您它是实体的哪一层。相反,必须从上下文推断有关名称实体性质的信息。
如果不可能进行这种推断,则必须说明:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | template <typename> struct Magic; // defined somewhere else template <typename T> struct A { static const int value = Magic<T>::gnarl; // assumed"value" typedef typename Magic<T>::brugh my_type; // decreed"type" // ^^^^^^^^ void foo() { Magic<T>::template kwpq<T>(1, 'a', .5); // decreed"template" // ^^^^^^^^ } }; |
在这里,名称
使
(如果你想亲自测试,这里有一个你可以使用的
1 2 3 4 5 6 7 8 9 10 11 12 | template <typename T> struct Magic { static const T gnarl; typedef T & brugh; template <typename S> static void kwpq(int, char, double) { T x; } }; template <> struct Magic<signed char> { // note that `gnarl` is absent static constexpr long double brugh = 0.25; // `brugh` is now a value template <typename S> static int kwpq(int a, int b) { return a + b; } }; |
用途:
1 2 3 4 5 6 7 | int main() { A<int> a; a.foo(); return Magic<signed char>::kwpq<float>(2, 3); // no disambiguation here! } |
由于
在同一主题上,有一个
只要类型名依赖于模板参数,就需要type name关键字(这样编译器就可以"知道"标识符(类型或值)的语义,而不必在第一次传递时使用完整的符号表)。
在使用通用模板参数(http://ideone.com/amimx)时,lone typename关键字的含义不同,也不太常见。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #include <string> #include <list> #include <vector> template <template <typename, typename> class Container, template <typename> class Alloc = std::allocator> struct ContainerTests { typedef Container<int, Alloc<int> > IntContainer; typedef Container<std::string, Alloc<int> > StringContainer; // void DoTests() { IntContainer ints; StringContainer strings; // ... etc } }; int main() { ContainerTests<std::vector> t1; ContainerTests<std::list> t2; t1.DoTests(); t2.DoTests(); } |