马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本文初发于 “天目中云的小站”,同步转载于此。
条款42 : 相识typename的双重意义
本条款中我们将相识typename的两种利用场景, 对typename的内涵及利用加深认知.
template声明式
在template的声明中, template<class T>和template<typename T>都是被允许的, 这两种写法并没有任何差异, C++对这两种写法等量齐观, 但是在真正利用中, 作者还是发起在传入自界说类时用class, 在传入恣意范例(包罗int等)时用typename, 如许会增长代码的可读性.
针对嵌套附属范例名称的应用
先让我们认识嵌套附属范例名称的界说 :
- 附属 : 依靠于某个template参数.
- 嵌套 : 在class内呈嵌套状.
- 附属嵌套范例名称 : 在class内呈嵌套状且依靠于某个template参数的范例名称.
我们通过下面的代码来明确 :
- template<typename C>
- void print2nd(const C& container)
- {
- if (container.size() >= 2) {
- C::const_iterator iter(container.begin()); // 这里的C::const_iterator便是从属嵌套类型名称
- ++iter;
- int value = *iter;
- std::cout << value;
- }
- }
复制代码 这段代码是无法通过编译的, 我们只有在前头加上typename才可以通过编译, 这是由于编译器早先并不确定C::const_iterator是一个范例名称, 以是当你明确指明其是一个范例名称之后, 编译器就可以正常运作了.
- typename C::const_iterator iter(container.begin()); // 这样就可以了
复制代码
- 以是为什么编译器无法确定这是一个范例名称呢?
实在是为了代码的严谨性, 我们举一个非常一点的例子 :
当我们写下如许的代码时, 编译器并不知道const_iterator是C中的范例还是成员变量, 如果它是成员变量的话, 那么这实在是一个乘法运算式, *是乘号; 如果他是范例, 那么这实在就是一个界说式, *代表着指针. 这两种情况都完全合法, 因此必要步调员明确指出其毕竟是什么才行.
两个例外
在一样平常情况下, typename必须作为嵌套附属范例名称的前缀词, 这一规则的例外是, typename不可出如今继承语句和初始值列表中, 这是C++中定死的, 没有须要去相识为什么, 记取就行.
- template<typename T>
- class Derived: public Base<T>::Nested { // 继承语句不可加typename
- public:
- explicit Derived(int x)
- : Base<T>::Nested(x) // 初始值列表不可加typename
- {
- typename Base<T>::Nested temp; // 这里可以加
- ...
- }
- };
复制代码 typename和typedef的组合利用
我们知道了typename会与嵌套附属范例名称绑定, 而且其着实一些情况下嵌套附属范例名称是很长的, 我们会风俗把typedef与typename组合, 将一个范例的誊写长度紧缩, 我们通过下面的例子相识 :
- template<typename IterT>
- void workWithIterator(IterT iter)
- {
- typedef typename std::iterator_traits<IterT>::value_type value_type;
- value_type temp(*iter);
- ...
- }
复制代码 这是这个组合的经典用法, 在STL标准库中就有大量的利用.
这里通过typedef将typename std::iterator_traits<IterT>::value_type这个云云长的范例紧缩到value_type, 不消想也肯定会镌汰大量的代码量. 至于为什么会有这么长的范例, 这与iterator_traits的萃取功能有关, 简朴来说就是IterT是一个迭代器范例,而iterator_traits可以根据iterT通过value_type萃取出迭代器所指向资源的真实范例T. 我们将在条款47中再作讨论这部门内容, 如果想深入学习的话也可以去STL源码分析中研读.
请记取 :
- typename作为template参数时, 和class意义完全类似.
- typename必须作为嵌套附属范例名称的前缀词, 除非在继承语句和初始值列表中.
- 将typedef和typename组合可以减小代码复杂度.
by 天目中云
|