Traits编程技法之type

    xiaoxiao2021-12-14  20

    STL对于性能的要求非常的严格,任何一点无意义的操作都会严重影响其中容器或算法的性能,即使只是一条语句。在高频率的使用下,这种浪费将会无限扩大。type_traits的作用之一就是提高性能。

    当我们在进行对象的析构(destroy)操作时,如果对象为内置对象(如int,char,float,pointer)或其数据成员包含内置对象,因为其析构操作由编译器内置执行,所以我们对其进行析构函数的调用是毫无意义的。

    试想,我们创造一个容器,其中包含的对象皆是内置类型的对象,若我们对如此多的对象逐一调用一个无关痛痒的destroy操作,那此容器的效率将会大大降低。

    所以我们需要一种手段,将那些有着无意义析构函数(trivial destructor)的类型挑选出来进行特殊处理:他们的析构操作我们什么也不需要做,交由编译器处理吧。这种手段就是type_traits,其将所有对象类型分为两类,一种的析构函数有意义,另一种的析构函数没有意义。这样我们就能分门别类的析构他们。

    下面我们一起探讨下如何实现type_traits。

    首先我们需要的是一个可以在函数间传递的"信息"。这个信息应该准确告诉我们,我们应该调用析构操作的哪个重载版本。众所周知,在函数间传递信息的方式有两种:参数或返回值。最简单直接的方式就是参数传递。但传递参数实质是对象或对象的拷贝的传递,所以,我们先创建两个对象,这两个对象什么也不干,唯一的作用就是帮助我们区分,待析构对象到底属于两类中的哪一类。

    这两个对象长这样:

    struct _true_type{};//无意义的析构函数 struct _false_type{};//有意义的析构函数说什么也不干,就什么也不干!这两个对象里什么也没有,即使频繁的作为参数传递也不会引起太多浪费(比起大量无意义的析构函数来说确实是九牛一毛)。

    那我们如何利用这两个对象呢?

    这时我们就需要利用模板特例化来分而治之:

    我们先创建一个基础类模板,先将所有类型都标为_false_type:

    template<typename T> struct type_traits { typedef _false_type has_trivial_default_constructor;//默认构造函数是否有意义? typedef _false_type has_trivial_copy_constructor;//拷贝构造函数是否有意义? typedef _false_type has_trivial_assgignment_constructor;//拷贝赋值操作是否有意义? typedef _false_type has_trivial_destructor;//析构函数是否有意义? /*POD意指Plain Old Data,也就是标量型别或传统的C struct(传统的C struct只能 包含数据成员,不能包含函数成员。也就是所谓的聚合类。POD型别必然包含无意义 的ctor/dtor/copy/assignment函数。 */ typedef _false_type is_POD_type;//是否为Plain Old Data? };

    然后,我们再为每个内置类型对象实现其特例化:

    #ifndef _STL_TEMPLATE_NULL #define _STL_TEMPLATE_NULL template<> #endif _STL_TEMPLATE_NULL struct type_traits <char> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <unsigned char> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <short> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <unsigned short> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <int> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <unsigned int> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <long> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <float> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <double> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; _STL_TEMPLATE_NULL struct type_traits <long double> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; template<typename T> struct type_traits <T*> { typedef _true_type has_trivial_default_constructor; typedef _true_type has_trivial_copy_constructor; typedef _true_type has_trivial_assgignment_constructor; typedef _true_type has_trivial_destructor; typedef _true_type is_POD_type; }; 当我们使用他们,例如进行析构操作时,我们可以实现两个重载函数,用_true_type对象或_false_type对象来区分他们:

    void _destroy(Iterator first, T value) { typedef typename type_traits<T>::has_trivial_destructor trivial_destructor; _destroy_aux(first, trivial_destructor()); } template<typename Iterator> void _destroy_aux(Iterator first, _false_type) { destroy_main(&*first);//有意义的析构函数,析构他! } template<typename Iterator> void _destroy_aux(Iterator first, _true_type){}//无意义的析构函数,那就不管我的事咯~ 有了_type_traits后,我们就可以实现更有效率的拷贝、赋值、析构操作了!

    转载请注明原文地址: https://ju.6miu.com/read-970655.html

    最新回复(0)