关于C++类型萃取

  最近在看《STL源码剖析》,关于C++类型萃取的问题看了几天,感觉还是有些疑惑。

  如果在C++中声明一个“以迭代器所指对象的类型”为类别,应当如何做。C++只支持sizeof(),并未支持typeof()!即便动用RTTI性质中的typeid(),获得的也只是型别名称,不能做变量声明只用。

  可以利用function template的参数推导(argument deducation)机制。

 1 template <class T>
2 struct MyIter {
3 typedef T value_type;
4 T* ptr;
5 MyIter(T* p=0) : ptr(p){}
6 T& operator*() const {retrun *ptr;}
7 //...
8 };
9
10 template <class I>
11 typename I::value_type
12 func(I ite)
13 { return *ite; }
14
15 //...
16 MyIter<int> ite(new int(8));
17 cout<< func(ite);

  以func()为对外接口,却把实际操作全部置于func_impl()之中,由于func_impl()是一个function template,一旦被调用,编译器会自动进行template参数推导。于是导出型别T,顺利解决问题。

  迭代器所指对象的型别,称为该迭代器的value type。如果value type用于函数的返回值,上面的方法也就行不通了,毕竟函数的"template参数推导机制"推而导之的只是参数,无法推导函数的返回值。

  如果采用内嵌型别,如下:

 1 template <class I, class T>
2 void func_impl(I iter, T t)
3 {
4 T tmp;
5 // ...
6 };
7
8 template <class I>
9 inline
10 void func(I iter)
11 {
12 func_impl(iter, *iter);
13 }
14
15 int main()
16 {
17 int i;
18 func(&i);
19 }

  func()的返回型别必须加上关键词typename,因为T是一个template参数,在它被编译器具现化之前,编译器对T一无所悉,换句话说,编译器此时并不知道MyIter<T>::value_type代表的是一个型别或是一个member function或是一个data member。关键词typename的用意在于告诉编译器这是一个型别,才能顺利通过编译。

  但并不是所有的迭代器都是class type。原生指针就不是,如果不是class type就无法为其定义内嵌性别。C++采用了template partialspecialization(偏特化)。class template专门用来"萃取"迭代器的特性,而value type正是迭代器的特性之一。

1 template <class I>
2 struct iterator_traits{
3 typedef typename I::value_type value_type;
4 };

  这个所谓的traits,其意义是,如果I定义有自己的value type,那么通过这个traits的作用,萃取出来的value_type就是I::value_type。换句话说,如果I定义有自己的value type,先前那个func()可以写成这样:

1 template <class I>
2 typename iterator_traits<I>::value_type
3 func(I ite)
4 { return *ite; }

  traits可以拥有特化版本,令iterator_traits拥有一个partial specialization如下:

1 template <class T>
2 struct iterator_traits<T*>{
3 typedef T value_type;
4 };

  于是,原生指针int*虽然不是一种class type,亦可以通过traits取其value type。traits所扮演的“特性萃取机”角色,萃取各个迭代器的特性。所谓的迭代器特性,指的是迭代器的相应型别(associated types)。

  而vector定义如下:

1 template <class T, class Alloc = alloc>
2 class vector {
3 public:
4 typedef T value_type;
5 typedef value_type* iterator;
6 ...
7 }

  而使用了两个typedef是为了使其有意义,便于理解,而没有进行类型的萃取。萃取机制是从一个指针萃取出指针所指的型别,而在上述的定义中,是将一个型别取地址,并没有使用iterator_traits进行萃取。

  

原文链接: https://www.cnblogs.com/yangbheb/archive/2011/10/17/2215069.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    关于C++类型萃取

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/34472

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午11:23
下一篇 2023年2月8日 上午11:24

相关推荐