C++ Type Traits的学习 (Boolan学习笔记第九周)

我们知道Traits是C++语言的一种高级特性。STL首先利用Traits技术对迭代器的特性做出规范, 制定出iterator_traits。后来SGI STL把它应用在迭代器以外的地方, 就有了type_traits的叫法。

我的理解是type traits是算法用来获取对象的一些重要信息,比如说是不是class,是不是function,有没有const, signed, volatile这些修饰符,有没有无用的构造函数之类的技术,根据 对象的这些信息就可以实现相关的操作。关于type traits的详细资料可参见
http://www.cplusplus.com/reference/type_traits/?kw=type_traits

有人可能会奇怪为什么要用traits或type_traits这些奇奇怪怪,绕来绕去的东西。用虚函数实现多态不就可以运行的时候实现不同的行为了吗?我的理解是,traits是编译时候就能决定的,虚函数多态是运行时候决定的,还得去查虚函数表,这样就比较慢。说白了还是为了效率的缘故 。

Traits和Type Traits实现的基础是函数模板+偏特化。如下图所示:
C++ Type Traits的学习 (Boolan学习笔记第九周)_第1张图片

注意这是C++ G2.9的代码。Type Traits首先定义了_true_type和_false_type这两个structure。然后给出了泛化和针对int和double的两个特化版本。可以看出,因为int和double都是Plain Old Data(POD)类型,所以它们的default_constructor, copy_constructor, assignment_operator, destructor 这些东西都不重要,其实根本就不需要,所以它们的has_trivial_xxxx都被定义为_true_type。而泛化版本的这些缺省都是 _false_type。这样,当算法询问一个 POD类型的对象有没有copy_contructor的时候, 就知道答案为否。

我们看看对于一个比较简单的class(不含指针),它的这些has_trival_xxxx会返回什么呢?我们可以测试一下这个Foo类:

class Foo
{
  private:
     int d1, d2;
};

测试结果

__has_trivial_assign 1
__has_trivial_copy 1
__has_trivial_constructor 1
__has_trivial_destructor 1

这个符合预期,因为class foo里面没有指针,所以上面4个函数都不重要,C++编译器给它们提供的缺省函数就够了。

我们再测试一下list,返回结果为

__has_trivial_assign 0
__has_trivial_copy 0
__has_trivial_constructor 0
__has_trivial_destructor 0

这个也符合预期, 因为list里面有指针嘛。

看来这个type traits很智能啊。它是怎么实现的呢?

对于POD类型,我们举一个简单的type traits is_integral,它用来看一个类型是不是整型,如果该类型是int/unsigned int/long/unsigned long/long long/unsigned long long/bool/char/signed char/unsigned char 之一,就返回true,否则就是false。

其具体实现如下
C++ Type Traits的学习 (Boolan学习笔记第九周)_第2张图片

我们可以看出它其实就是在玩类模板和特化而已。

如果深入到类的话,应该就没这么简单了。应该是编译器里面加了很多代码,比如说看一个class的话里面有没有指针,从而做出相应判断。

你可能感兴趣的:(C++)