Boolan C++ 第十周 三种巧妙的模板技术

2017-03-30  本文已影响0人  wild_horse

模板作为C++语言特性的一个重要组成部分,被广泛用在范式编程中,在标准库中经常可以看到一些非常让人拍案叫绝的模板技术。在课程中接触到这些技术,做个整理和总结。

一. variadic templates

实现这一特性的方法是通过递归算法,一次处理一个目标参数,直到处理到最后的模板参数作为递归基返回。
以标准库的hash函数为例

template<typename... Types>
size_t hash_all(const Types&... args)
{
    size_t seed=0;
    hash_val(seed,args...); //进入计算
    return seed;
}

template<typename T,typename... Types>
void hash_val(size_t &seed,
            const T& val,const Types&... args)
{
    //处理第一个模板参数
    hash_combine(seed,val);
    //递归
    hash_val(sed,args...);
}

//处理到最后一个参数
template<typename T>
void hash_val(size_t &seed,const T& val)
{
    hash_combine(seed,val);
}
//对模板参数进行处理
#include <functional>
template<typename T>
void hash_combine(size_t &seed,const T  &val)
{
    seed^=std::hash<T>()(val)+0x9e3779b9
    +(seed<<6)+(seed>>2);
}

二. tuple的参数处理

template<typename... Values> class tuple;
//继承链的最顶端
template<> class tuple<>{};
template<typename Head,typename... Tail>
class tuple<Head,Tail...>
    :private tuple<Tail...>
    {
        typedef tuple<Tail...> inherited;
    public:
        tuple(){}
        tuple(Head v,Tail... vtail)
        :m_head(v),inherited(vtail...){}
        typename Head::type head() {    return m_head;  }
        inherited &tail()   {   return *this;   }
    protected:
        Head m_head;
    };

tuple的设计是利用继承链的最低端,在构造函数中对它的直接基类进行初始化,而它的基类又对基类的直接基类进行初始化,不断递归,直到直接基类是个空类为止。

//以tuple(1,2.3,"hello")为例
tuple<int,float,string> t(1,2.3,"hello");
t.head() ; //1
t.tail();  //(2.3,"hello")
t.tail().head(); //2.3

三. type traits的设计

标准库为我们提供了很多的type traits的模板类型,我们可以用来初始化获得类型的相关信息。
以 is_void为例,用来判断是不是void类型,解决思路是把对象的一些其他类型去除再来判断是否为void

//去除 const 的属性
template<typename T>
struct remove_const
{
    typedef T type;
};
template<typename T>
struct remove_const<T const>
{
    typedef T type;
};
//去除 volatile 的属性
template<typename T>
struct remove_volatile
{
    typedef T type;
};
template<typename T>
struct remove_volatile<T volatile>
{
    typedef T type;
};
//去除 const volatile 的属性
template<typename T>
struct remove_cv
{
    typedef typename remove_const<typename remove_volatile<T>::type>::type type;
};

template<typename>
struct __is_void_helper
:public false_type{};
template<>
struct __is_void_helper<void>
:public true_type{};
template<typename T>
//最后继承 false_type 或 true_type
struct is_void
:public __is_void_helper<typename remove_cv<T>::type>::type{};

运用到模板的特化解决问题,很多思路都是可以借鉴的

上一篇下一篇

猜你喜欢

热点阅读