C++中的关键字typename

原创 2007年10月10日 15:47:00


近来想做对LIST的更方便使用的模板类,头文件如下:

#include "config.hpp"

namespace System
{
 namespace Collections
 {
  template<class ValueType>
  class List
  {

  public:
   List();
   virtual ~List();
   virtual int Add(ValueType value);
   virtual bool Contains(ValueType value);
   virtual void Delete(int index);
   virtual ValueType GetByIndex(int index);
   virtual int GetCount();
   virtual void Insert(int index, ValueType value);
   virtual void InsertAfter(ValueType item, ValueType value);
   virtual void InsertBefore(ValueType item, ValueType value);
   virtual void Update(int index, ValueType value);
   virtual shared_ptr<ValueType> Prev(ValueType value);
   virtual shared_ptr<ValueType> Next(ValueType value);

  private:
   shared_ptr<list<ValueType> > items;
  };
 }
}

 实现文件如下:

#include "List.hpp"

using System::Collections::List;

template<class ValueType>
List<ValueType>::List()
{
 items = new shared_ptr<list<ValueType> >;
}

template<class ValueType>
 List<ValueType>::~List()
{}
.
.
.
template<class ValueType>
 void List<ValueType>::InsertAfter(ValueType item, ValueType value)
{
 if(!items)
 {
  throw new shared_ptr<exception>(new exception("items hadn't been initialized!"));
 }
 //程序编译时提示这儿会出错:提示信息为expect ';' before itemiterator
if((items::iterator itemiterator = find(items.begin(),items.end(),item)) != items.end())
  items.insert(itemiterator,value); 
.
.
.
后来检查全部代码,发现没有什么错误,后来到网上搜索到,应该在声明itemiterator时,在前面加上C++关键字:typename
改后的代码如下:

typename list<ValueType>::iterator itemiterator;
 itemiterator = find(items.begin(),items.end(),item);
 if(itemiterator != items.end())
  items.insert(itemiterator,value);
}

.
.
.
看来还是自己对C++不熟悉,于是从箱子底下翻出了N久以前的<<C++ Template>>
解释如下:


 关键字typename是C++标准化过程中被引入的,目的在于向编译器说明template内的某个标识符是类型(而不是其它什么东西),考虑下面的例子:
template <typename T>
   class MyClass{
          typename T::SubType * ptr;
          ...
};
在这里,第二个typename关键字的意思是:SubType是class T内部定义的一个类型,因此ptr是一个指向T::SubType类型的指针。
如果没有使用关键字typename,SubType会被认为是class T的一个static成员,于是被编译器理解为一个具体变量,从而导致以下表达式:
 T::SubType * ptr
所表达的意义变成:class T的static成员SubType与ptr的乘积。

:Visual C++ 6.0/ICL 7.1/G++ 3.2在上述的MyClass被实例化之前,都假设SubType是成员类型,因此认为上述例子是正确的,Visual C++ 7.1认为这是错误的(Visual C++ 7.1 对类型要求极其严格),然而当具体实例化时,如果SubType不是一个成员类型,四个编译器都会报错。

通常如果某个与template parameter相关的名称是个类型的时候,你就必须加上关键字typename。更详细的讨论见<<C++ Template>> p130

typename的一个典型应用是在template程序代码中使用STL容器提供的迭代器(iterators):

//basic/printcoll.hpp
#include <iostream>

//print elements in a STL container
template <typename T>
void printcoll(T const& coll)
{
     typename T::const_iterator pos;
     typename T::const_iterator end(coll.end());
    
     for (pos = coll.begin();pos != end;++pos)
     {
             std::cout << *pos << '';
     }
     std::cout << std::endl;
}

在这个function template中,coll是个STL容器,其元素类型为T。这里使用了STL容器的迭代器类型(iterator type)循环访问coll的所有元素,迭代器类型为const_iterator,每一个STL容器都有这种类型:

class stlcontainer {
       ...
       typedef ... iterator;                //可读写迭代器
       typedef ... const_iterator;   //只读迭代器
       ...
};

使用template type T的const_iterator时,你必须写出全名,并在最前面加上关键字typename:

typename T::const_iterator pos;

.template构造函数

引入关键字typename之后,又出现了一个类似的问题,考虑下面的程序代码,其中使用标准的bitset类型:

template<int N>
void printBitset(std::bitset<N> const& bs)
{
     std::cout << bs.template to_string<char,char_traits<char>,allocator<char> >();
}


/*  你也可以充分利用bitset的member typedef 像下面这样:
std::cout << bs.template to_string<std::string::value_type,
      std::string::traits_type,
      std::string::allocator_type>();*/

此例中的.template看起来有点儿怪,但是如果没有它,编译器无法知道紧跟其后的 "<" 代表的是template argument list的起始,而非是一个小于符号,注意,只有当位于“.”之前的构造取决于某个template parameter时,这个问题才会发生。以上例子中,参数bs便是取决于template parameter N.

结论是“.template”或“->template”标记只有在templates之内才能被使用,而且他们必须紧跟着“与template parameters相关的”。

我的编程环境:Ubuntu G++ boost-1_34_1

C++中的typename关键字

在C++中typename除了用于在定义模板函数和模板类中来替代关键字class,例如template换成template意外,typename还可以用来做型别的定义。 注意:下面的代码是有问题的 ...
  • u010585135
  • u010585135
  • 2015年01月21日 10:56
  • 741

C++ - 模板(template)中typename的使用方法

模板(template)中typename的使用方法 http://blog.csdn.net/caroline_wendy/article/details/23910709 声明templ...
  • u012515223
  • u012515223
  • 2014年04月17日 10:31
  • 10089

C++ typename的起源与用法

目录 起因typename的常见用法typename的来源一些关键概念 限定名和非限定名依赖名和非依赖名类作用域 引入typename的真实原因 一个例子问题浮现千呼万唤始出来不同...
  • somestill
  • somestill
  • 2016年03月03日 15:41
  • 3251

C++ typename关键字的作用

参考:http://blog.163.com/cp7618@yeah/blog/static/70234777201122111034365/原文详细讲解typedef和typename的作用与区别 ...
  • qq2399431200
  • qq2399431200
  • 2013年06月01日 09:46
  • 622

c++ typename 关键字扫盲

typedef _CharT char_type; typedef _Traits traits_type; typedef typename traits...
  • statdm
  • statdm
  • 2013年01月08日 11:09
  • 4599

C++ typename关键字的作用

参考:http://blog.163.com/cp7618@yeah/blog/static/70234777201122111034365/原文详细讲解typedef和typename的作用与区别 ...
  • qq2399431200
  • qq2399431200
  • 2013年05月29日 09:45
  • 759

C++ Template 基础篇(三):参数魔法

Template 基础篇-参数魔法Template所代表的泛型编程是C++语言中的重要的组成部分,我将通过几篇blog对这半年以来的学习做一个系统的总结,本文是基础篇的第三部分。Template 基础...
  • lezardfu
  • lezardfu
  • 2017年03月05日 12:24
  • 335

C++中typename关键字的使用方法和注意事项

C++中typename关键字的使用方法和注意事项     1, 什么地方使用?用在模板定义里,标明其后的模板参数是类型参数。     例如  tem...
  • qq_26399665
  • qq_26399665
  • 2016年06月11日 18:52
  • 697

C++中typename关键字的使用方法和注意事项

原文地址:http://blog.csdn.net/pizzq/article/details/1487004 解决了遇到的一个问题,转载备忘! 1, 什么地方使用?用在模板定...
  • xiaoyaohuqijun
  • xiaoyaohuqijun
  • 2016年03月30日 20:05
  • 170

C++ 的模板中 typename 关键字的用法

typename的使用场合:用处1, 用在模板定义里, 标明其后的模板参数是类型参数。 例如template T foo(const T& t, const Y& y){//....};templa...
  • qq_38216239
  • qq_38216239
  • 2017年11月03日 15:03
  • 38
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中的关键字typename
举报原因:
原因补充:

(最多只允许输入30个字)