typedef typename有什么作用??

上善若水邻 2011-02-14 01:41:43
摘自STL源码剖析。
3.6 iterator 源码完整重列
由于讨论次序的缘故,先前所列的源码切割散落,有点凌乱。以㆘重新列出SGI STL
<stl_iterator.h> 表头档内与本章相关的程序代码。该表头档还有其他内容,是
关于iostream iterators、inserter iterators 以及reverse iterators 的实作,将于第8 章
讨论。

// 节录自SGI STL <stl_iterator.h>
// 五种迭代器类型
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
// 为避免写码时挂㆒漏万,自行开发的迭代器最好继承自㆘面这个std::iterator
template <class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&>
struct iterator {
typedef Category iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
};
// 「榨汁机」traits
template <class Iterator>
struct iterator_traits {
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
};
// 针对原生指标(native pointer)而设计的traits 偏特化版。
template <class T>
struct iterator_traits<T*> {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference;
};
//下面是我加来测试的,发现编译器提示,error-type;
//我打开VS中的源码发现不是这么用的。
//VS中是typedef一个类型 然后用新声明的类型typedef typename;
int main()
{
iterator_traits<int>::difference_type d;
}

...全文
841 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
liutengfeigo 2011-02-14
  • 打赏
  • 举报
回复
typename 的双重含义
参考<Effective c++>
bluesky12312388 2011-02-14
  • 打赏
  • 举报
回复
typedef typename F::type type_value;
上面这句的typename告诉编译器F是一个类模板或是结构模板

typedef typename CT<F>::type value;
上面这句的typename是必须的,至于为什么现在还不明白。
=====================================================
因为编译器不知道CT<F>::type这里的type到底是类型还是一个static值,
编译会假设这是一个值,除非你告诉它,所以这里的typename是必须的。

一般性规则很简单:任何时候当你想要在template中指涉一个
嵌套人性类型名称时 ,
那就必须在紧邻它的前一个位置放上关键字typename(有一个
例外不可放在成员初值列中作为base class的修饰符)
如:
template <typename T>
class Derived:public Base<T>::Nested //这里就不需要typename
{}
参考:《Inside C++ Object Modal》P205 了解typename的双重意义
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复

#include<iostream>
using namespace std;
template<typename T>
class CT
{
public:
typedef T type;
};
template<typename F>
class CF
{
public:
//下面两个我觉得应该是等效,主要区别是在使用时的区别
//如果使用时定义如下,CF<int>::value x=0;
//typedef typename F::type type_value;这句就会报错。
//但是typedef typename CT<F>::type value;就不会报错
typedef typename F::type type_value;
typedef typename CT<F>::type value;
};
int main()
{
////这里出错了,因为需要传递进来的是模板类不能是内置类型。
//CF<int>::type_vale x;
CF<CT<int>>::type_value i=0; //正确传进来的是模板。
int j=0;
if(typeid(i) == typeid(j))
cout<<"yes";
}

翻开几本电子书看模板相关内容没看明白。
但是经过楼上的几位指点后,再GOOGLE才明白。
我前两次贴的代码错的是在使用时,声明并没有错。

typedef typename F::type type_value;
上面这句的typename告诉编译器F是一个类模板或是结构模板

typedef typename CT<F>::type value;
上面这句的typename是必须的,至于为什么现在还不明白。
不知道我的理解对不对?望高手指点谢谢。
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 bluesky12312388 的回复:]
这种情况下要加上typename,因为不加编译器有
可能将iterator<Iterator>::iterator_category试图
解释为变量,你在typedef 就会有语法错误。
加上以后就是让编译器认为iterator<Iterator>::iterator_category它是一个类型
[/Quote]
我10楼的正确还是帖子原文正确?谢谢!
bluesky12312388 2011-02-14
  • 打赏
  • 举报
回复
这种情况下要加上typename,因为不加编译器有
可能将iterator<Iterator>::iterator_category试图
解释为变量,你在typedef 就会有语法错误。
加上以后就是让编译器认为iterator<Iterator>::iterator_category它是一个类型
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复

#include<iostream>
using namespace std;
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
// 为避免写码时挂㆒漏万,自行开发的迭代器最好继承自㆘面这个std::iterator
template <class Category/*, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&*/>
struct iterator {
typedef Category iterator_category;
/*typedef T value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
*/
};
// 「榨汁机」traits
template <class Iterator>
struct iterator_traits {
typedef typename iterator<Iterator>::iterator_category iterator_category;
/*typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
*/
};
int main()
{
iterator_traits<int>::iterator_category d;
}

我按照5楼建议简单看了下,发现也是如我现在这样的用法。
现在编译器没有提示错误了,不知道我现在的写法正确??还是原来的正确??
谢谢。
qq120848369 2011-02-14
  • 打赏
  • 举报
回复
是一个语法规定,有模板的情况下写上了才是类型。
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 thefirstz 的回复:]
如果不加typename,编译器会认为::后面的是static类型成员变量,而不是一个类型
typename Iterator::iterator_category iterator_category;
-------------------------------
不加的话就不会认为iterator_category是变量类型
[/Quote]
你说说上面的代码编译器为什么提示有错误????
qq120848369 2011-02-14
  • 打赏
  • 举报
回复
是一个语法规定,有模板的情况下写上了才是类型。
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 pengzhixi 的回复:]
看trait那章节
[/Quote]
谢谢.我先看看,看不明白再请教.
pengzhixi 2011-02-14
  • 打赏
  • 举报
回复
看trait那章节
上善若水邻 2011-02-14
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 bdmh 的回复:]
去看模板的使用
[/Quote]
哦,等下我去看看.
nicklisir 2011-02-14
  • 打赏
  • 举报
回复
typedef typename Iterator::iterator_category iterator_category;
这个typename说明它是个类或结构 ;没有的话默认它是成员【Iterator::iterator_category】;
typedef 是用来取别名,方便使用;
看下cprimer 中的模板注意事项;那比较详细
昵称很不好取 2011-02-14
  • 打赏
  • 举报
回复
如果不加typename,编译器会认为::后面的是static类型成员变量,而不是一个类型
typename Iterator::iterator_category iterator_category;
-------------------------------
不加的话就不会认为iterator_category是变量类型
bdmh 2011-02-14
  • 打赏
  • 举报
回复
去看模板的使用

65,180

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧