C++ typedef和typename关键字
来源:互联网 发布:恶搞锁屏软件 编辑:程序博客网 时间:2024/06/07 03:35
前序
在《STL源码解析》一书中看到了这样一段代码
template <class ForwardIterator, class Size, class T, class T1>inline ForwardIterator __uninitialized_fill_n(ForwardIterator first, Size n, const T& x, T1*){ typedef typename __type_traits<T1>::is_POD_type is_POD; return __uninitialized_fill_n_aux(first, n, x, is_POD());}
在代码的第三行中出现的
typedef typename __type_traits<T1>::is_POD_type is_POD;
可能会让初学者感到无法理解,难以接受。这里的typedef 还好理解,但是typename又是啥鬼?:tw-1f62c:
在《C++Primer 5th》P593页和《Effective C++》第42条都讲解了这部分内容,我也总结了下给大家,方便大家解惑。
类型别名typedef
类型说明的格式为:
typedef 类型 定义名;
它用来对一个数据类型取一个新名字。其中定义名表示这个类型的新名字。
例如:
typedef int type_int; // 这里的type_int就是整形int的另一个名字,接下来可以用type_int代替int
类型解释typename
定义
在维基百科中这样解释:
当用于泛型编程时是另一术语”class”的同义词。这个关键字用于指出模板声明(或定义)中的非独立名称(dependent names)是类型名,而非变量名。
例如声明一个人的模板类
template <typename T>class Person{ // .... };// 或者template <class T>class Person{};
使用类的类型成员
通常我们使用作用域运算符(::)来访问static成员和类型成员。在普通(非模板)代码中,编译器掌握类的定义。因此,他知道通过作用域运算符访问的名字是类型还是static成员。例如:string::size_type,编译器有string的定义,从而知道size_type是一个类型。
但是如果是模板类就变得很困难了。
例如:
template <typename C>void print2nd(const C& contrainer){ // ... C::const_iterator* x; // 申明x为一个指针,指向C::const_iterator // ...};
这段代码看起来好像是对,但是它确实是错的,回到之前我们之所以认为它对,是因为我们“知道”C::const_iterator是一个类型,但是如果C::const_iterator不是一个类型呢,如果它是一个static成员变量呢?又或者是一个全局变量呢?那么上述的用法就变为相乘了。
因此有必要说明C::const_iterator是一个类型。只要在紧邻它之前放置关键字typename即可
例如
template <typename C>void print2nd(const C& contrainer){ // ... typename C::const_iterator* x; // 申明x为一个指针,指向C::const_iterator // ...};
这个规则很简单:在任何时候当你想在template中涉及一个嵌套从属类型名称,就必须在紧临它的前一个位置放置上关键字typename(也有例外)
“typename作为嵌套从属类型名称的前缀词”的例外
template 不可以出现在base classes list内的嵌套从属类型名称之前,也不可以出现在memeber initialization list(成员初始列表)中作为base class 修饰词, 例如:
template <typename T>class Derived : public Base<T>::Nested // Base classes list,不允许出现"typename"{public: explicit Derived(int x) : Base<T>::Nested(x) // 成员初始化列表,不允许出现"typename" { typename Base<T>::Nested temp; // 嵌套从属类型名称 }};
typedef和typename共用
回到最初的问题,这里我们用另外一个例子代替
template <typename IterT>void workWithIterator(IterT iter){ typename std::iterator_traits<IterT>::value_type temp(*iter);}
看起来任然可能有点蒙, 所以先讲下traits
traits(特性萃取机)
在我们日常中,常用到的迭代器相应型别有5中:value_type, difference_type, pointer, reference, iterator catagoly。而“特性萃取机”traits会忠实的原汁原味的榨取出来:
template <class I>struct iterator_traits{ typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename I::difference_type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference;}
而std::iterator_traits<IterT>::value_type
说的就是”类型为IterT之对象所指之物的类型”
如果你的IterT为vector<int>::iterator
,temp的类型就是int,
如果你的IterT为list<sting>::iterator
,temp的类型就是string
说完上面哪行代码就解释的通了 std::iterator_traits<IterT>::value_type
是一个嵌套从属类型名(value_type被嵌套与iterator_traits<IterT>
之内而IterT是一个template参数),所以必须在它之前放置typename
而为了简化书写,加上typedef,完美:tw-1f604:
最终代码
template <typename IterT>void workWithIterator(IterT iter){ typedef typename std::iterator_traits<IterT>::value_type value_type; value_type temp(*iter); // .....}
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typename和typedef关键字
- typename和typedef关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- typedef和typename关键字
- unity 脚本的执行先后顺序
- 从零开始搭建Raspberry Pi机器视觉编程环境
- Android Studio显示行数
- WinSCP 中普通用户以 root 身份登录 Linux
- c#txt文件存到string数组中报错
- C++ typedef和typename关键字
- CSS3 修改和去除移动端点击事件出现的背景框 (tap-highlight-color)
- Qt之XML
- rs232和rs485区别
- linux精炼代码记录:skip_atoi
- C++与OC混合编程初步
- error while loading shared libraries 错误解决办法总结,
- VS2015,1>cl : Command line error D8016: '/ZI' and '/Gy-' command-line options are incompatible
- EL表达式用法