美文网首页
Boolan C++ 第十周 三种巧妙的模板技术

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

作者: wild_horse | 来源:发表于2017-03-30 23:44 被阅读0次

    模板作为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{};
    

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

    相关文章

      网友评论

          本文标题:Boolan C++ 第十周 三种巧妙的模板技术

          本文链接:https://www.haomeiwen.com/subject/zgxmottx.html