zoukankan      html  css  js  c++  java
  • Templates<2>

     Part:template specialized

    Part1:template specialized

    #include <iostream>
    #include <stdio.h>
    using namespace std;
    template <typename To,typename From>
    struct CastAndPrint
    {
        CastAndPrint(From f){
            cout << (To)f <<endl;
        }
    };
    
    template <typename To>
    struct CastAndPrint<To,const char*>
    {
        CastAndPrint(const char *s){
            cout << (To)atoi(s) <<endl;
        }
    };
    
    
    int main()
    {
        CastAndPrint<int,float>(1.232f);
        CastAndPrint<int,const char*>("67");
        CastAndPrint<char,const char*>("67");
        return 0;
    }
    View Code

    part2:Trait & Policy

    (1) accumulation,可能的累积定义

    //
    // Created by Administrator on 2017/8/12.
    //
    
    #ifndef TP_CP15_ACCUM_ACCUMTRAITS_H
    #define TP_CP15_ACCUM_ACCUMTRAITS_H
    
    #include <iostream>
    
    template <typename T>
    class AccumulationTraits;
    
    template <>
    class AccumulationTraits<char>
    {
    public:
        typedef int AccT;
    };
    
    template <>
    class AccumulationTraits<short>
    {
    public:
        typedef int AccT;
    };
    
    template <>
    class AccumulationTraits<int>
    {
    public:
        typedef int AccT;
    
    };
    
    template <>
    class AccumulationTraits<float>
    {
    public:
        typedef double AccT;
    
    };
    
    
    #endif //TP_CP15_ACCUM_ACCUMTRAITS_H
    accumtraits.h
    #ifndef TP_CP15_ACCUM_ACCUM2_H
    #define TP_CP15_ACCUM_ACCUM2_H
    
    #include <iostream>
    #include "accumtraits.h"
    template <typename T> typename
    AccumulationTraits<T>::AccT accum(T const*begin,T const*end)
    {
        typedef typename AccumulationTraits<T>::AccT AccT;
        AccT total = AccT();
        while(begin!=end)
        {
            total += *begin;
            ++begin;
        }
        return total;
    }
    
    
    
    #endif //TP_CP15_ACCUM_ACCUM2_H
    accum2.h
    #include <iostream>
    #include "accum2.h"
    using namespace std;
    int main()
    {
    
        int val[]{1,2,3,4,5};
        cout << accum(val,val+5) <<endl;
    
        char val2[] = "AA";
        cout << accum(val2,val2+3) <<endl; //130
    
        return 0;
    }
    main.cpp

     (2) Trait 和 Policy为我们的程序提供一个用户可以编辑的模版接口

    accumlation.h把所有的定义都写了

    //
    // Created by Administrator on 2017/8/13.
    //
    
    #ifndef TP_CP15_ACCUMTRAITS2_ACCUMULATION_H
    #define TP_CP15_ACCUMTRAITS2_ACCUMULATION_H
    
    
    // ============================ Traits ===============================
    template <typename T>
    class AccumulationTraits;
    
    template <>
    class AccumulationTraits<char>
    {
    public:
        typedef int AccT;
        static AccT zero() { return 0;}
    };
    
    template <>
    class AccumulationTraits<int>
    {
    public:
        typedef int AccT;
        static AccT zero() { return 0;}
    };
    
    template <>
    class AccumulationTraits<short>
    {
    public:
        typedef int AccT;
        static AccT zero() { return 0;}
    };
    
    template <>
    class AccumulationTraits<unsigned int>
    {
    public:
        typedef unsigned long AccT;
        static AccT zero() { return 0;}
    };
    
    template <>
    class AccumulationTraits<float>
    {
    public:
        typedef float AccT;
        static AccT zero() { return 0.0f;}
    };
    
    // ============================ Traits ===============================
    
    
    // define one Simple Policy for our defaults
    class SumPolicy
    {
    public:
        template <typename T1,typename T2>
        static void accumulate (T1 &total, T2 const &value)
        {
            total += value;
        }
    };
    
    
    
    //
    template <typename T,
            typename Policy = SumPolicy,
            typename Traits = AccumulationTraits<T> >
    class Accum
    {
    public:
        typedef typename Traits::AccT AccT;
        static AccT accum(T const*begin, T const *end)
        {
            AccT total = Traits::zero();
            while (begin!=end)
            {
                Policy::accumulate(total,*begin);
                begin++;
            }
            return total;
        }
    };
    
    
    
    
    
    #endif //TP_CP15_ACCUMTRAITS2_ACCUMULATION_H
    accumlation.h

    main.cpp提供了2个新Policy接口,但是我们的乘法接口会出现问题,因为初值zero()

    #include <iostream>
    #include "accumulation.h"
    
    //
    class DoubleAddPolicy
    {
    public:
        template <typename T1,typename T2>
        static void accumulate(T1 &total , T2 const &value)
        {
            total += 2 * value;
        }
    };
    
    class MultPolicy
    {
    public:
        template <typename T1,typename T2>
        static void accumulate(T1 &total , T2 const &value)
        {
            total *= value;
        }
    };
    
    
    
    using namespace std;
    int main()
    {
        int val[]{1,2,3,4,5,6};
        cout << Accum<int>::accum(val,val+6) <<endl;
    
        char cval[] =  "AA";
        cout << Accum<char>::accum(cval,cval+2)<<endl;
    
        float fval[]{1.0,2.0,3.0,4.0,5.0};
        cout << Accum<float>::accum(fval,fval+5)<<endl;
    
        cout << Accum<float,DoubleAddPolicy>::accum(fval,fval+5) <<endl;
    
    
        // but next result will is zero,because our value initialized to zero
        cout << Accum<float,MultPolicy>::accum(fval,fval+5) <<endl;
        return 0;
    }
    main.cpp

    Part3:Type function

    (1) 确定容器元素类型

    #include <iostream>
    #include <vector>
    #include <stack>
    #include <typeinfo>
    #include <list>
    using namespace std;
    
    
    // class give the type size
    template <typename T>
    class TypeSize
    {
    public:
        static size_t const value = sizeof(T);
    };
    
    
    // what element type in a container
    template <typename T>
    class ElementT;   // basic template
    
    // vector<>
    template <typename T>
    class ElementT<vector<T>>
    {
    public:
        typedef T type;
    };
    
    // list<>
    template <typename T>
    class ElementT<list<T>>
    {
    public:
        typedef T type;
    };
    
    // stack<>
    template <typename T>
    class ElementT<stack<T>>
    {
    public:
        typedef T type;
    };
    
    template <typename T>
    void print_element(T const &c)
    {
        cout << "Container of " << typeid(typename ElementT<T>::type).name() << endl;
    }
    
    
    // but lots of containers have it's own value_type,so we can use this method
    template <typename T>
    void print_valueType(T const &c)
    {
        cout << "Container of " << typeid(typename T::value_type).name()<< endl;
    }
    
    
    int main()
    {
        cout << TypeSize<char>::value <<endl;
        cout << TypeSize<short>::value <<endl;
        stack<int> s;
        vector<float> s2;
        print_element(s);
        print_element(s2);
        print_valueType(s2);
    
    
        return 0;
    }
    View Code

    (2) Why the container::value_type is import?

    检查一个类型是类,还是不是类(SFINAE,substitution-failure-is-not-error,替换失败并非错误):

    #include <iostream>
    
    template <typename T>
    class IsClassT
    {
    private:
        typedef struct {char a[2];} char2;
        template <typename C>
        static char test(int C::*);
    
        template <typename C>
        static char2 test(...);
    
    public:
        enum{Yes=sizeof(IsClassT<T>::test<T>(0)) == 1};
        enum{No = !Yes};
    
    };
    template <typename T>
    void check()
    {
        if(IsClassT<T>::Yes)
        {
            std::cout << "IsClassT" <<std::endl;
        }
        else
        {
            std::cout << "!IsClassT" <<std::endl;
        }
    
    }
    class Data
    {
    
    };
    
    
    int main()
    {
        check<int>();
        check<Data>();
        return 0;
    }
    View Code

     具体(SFINAE)解释程序:

    #include <iostream>
    using namespace std;
    
    typedef struct char2
    {
        char a[2];
    }char2;
    
    
    template <typename T>
    char test(int T::*);
    
    template <typename T>
    char2 test(...);
    
    class Value
    {
    
    };
    
    
    int main(int argc, char const *argv[])
    {
        std::cout <<sizeof(char)  <<endl;    // 1
        std::cout <<sizeof(char2) <<endl;    // 2
    
    
        std::cout << sizeof(test<int>(0)) << endl;    // 2,select test(...) function
        std::cout << sizeof(test<Value>(0)) << endl;  // 1,select test(int T::*) function
    
        return 0;
    } 
    View Code

     Promotion trait:

    #ifndef INC_15_2_4_IFTHENELSE_HPP_H
    #define INC_15_2_4_IFTHENELSE_HPP_H
    
    
    
    template <bool C, typename Ta , typename Tb>
    class IfThenElse;
    
    
    template <typename Ta,typename Tb>
    class IfThenElse<true,Ta,Tb>
    {
    public:
        typedef Ta value_type;
    };
    
    
    template <typename Ta,typename Tb>
    class IfThenElse<false,Ta,Tb>
    {
    public:
        typedef Tb value_type;
    };
    
    
    
    
    
    
    
    
    
    
    #endif //INC_15_2_4_IFTHENELSE_HPP_H
    ifthenelse.hpp
    #ifndef PROMOTE_HPP_H_
    #define PROMOTE_HPP_H_
    #include <vector>
    #include "ifthenelse.hpp"
    
    template <typename T1,typename T2>
    class Promotion;
    
    
    template <typename T1,typename T2>
    class Promotion
    {
    public:
        typedef typename IfThenElse<(sizeof(T1) > sizeof(T2)),T1,T2>::value_type value_type;
    };
    
    template <typename T>
    class Promotion<T,T>
    {
    public:
        typedef T value_type;
    };
    
    template <typename T1,typename T2>
    class Promotion<std::vector<T1>,std::vector<T2>>
    {
    public:
        typedef std::vector<typename Promotion<T1,T2>::value_type > value_type;
    };
    
    template <typename T>
    class Promotion<std::vector<T>,std::vector<T>>
    {
    public:
        typedef std::vector<typename Promotion<T,T>::value_type > value_type;
    };
    
    
    
    #endif
    promote.hpp
    #include <iostream>
    #include "promote.hpp"
    #include <algorithm>
    using namespace std;
    template <typename T1,typename T2>
    typename Promotion<T1,T2>::value_type add(T1 val1,T2 val2)
    {
        return val1+val2;
    }
    
    template <typename T1,typename T2>
    typename Promotion<vector<T1>,vector<T2>>::value_type add(const vector<T1> &val1,
                                                              const vector<T2> &val2)
    {
        typename Promotion<vector<T1>,vector<T2>>::value_type result;
        for(int i=0;i<val1.size();i++)
        {
            result.push_back(val1[i] + val2[i]);
        }
        return result;
    };
    
    
    int main()
    {
        std::cout <<add(2,2.0f)<< std::endl;
        vector<int> val_01(3);
        fill(val_01.begin(),val_01.end(),1);
        vector<float> val_02(3);
        fill(val_02.begin(),val_02.end(),2.0f);
        auto result = add(val_01,val_02); // vector<float>
        for_each(result.begin(),result.end(),[](const float &val){cout << val << endl;});
    
        return 0;
    }
    main.cpp

     Metaprogram:

     <1>计算一个数的n次方 

    #include <iostream>
    
    template <int S,int N>
    class pow
    {
    public:
        enum {result = S*pow<S,N-1>::result};
    };
    
    template <int S>
    class pow<S,0>
    {
    public:
        enum{result = 1};
    };
    
    template <int N>
    class pow<0,N>
    {
    public:
        enum{result};
    };
    
    template <>
    class pow<0,0>
    {
    public:
        enum{ result};
    };
    
    
    int main()
    {
        std::cout << pow<3,2>::result <<std::endl;  // 3^2
        std::cout << pow<2,2>::result <<std::endl;  // 2^2
        return 0;
    }
    View Code

     上面的代码依然可以用static int const result 代替:

    #include <iostream>
    
    template <int S,int N>
    class pow
    {
    public:
        static const int result = S*pow<S,N-1>::result;
    };
    
    template <int S>
    class pow<S,0>
    {
    public:
        static const int result = 1;
    };
    
    template <int N>
    class pow<0,N>
    {
    public:
        static const int result = 0;
    };
    
    template <>
    class pow<0,0>
    {
    public:
        static const int result = 0;
    };
    
    
    int main()
    {
        std::cout << pow<3,2>::result <<std::endl;  // 3^2
        std::cout << pow<2,2>::result <<std::endl;  // 2^2
        return 0;
    }
    View Code

     不过static int 出来的数据永远是个左值。

    <2>For循环展开:

    (1)图形学dot()函数

    #include <iostream>
    template <int DIM, typename T>
    class DotProduct
    {
    public:
        static T result(T *a,T *b)
        {
            return (*a) * (*b) + DotProduct<DIM-1,T>::result(a+1,b+1);
        }
    };
    template <typename T>
    class DotProduct<1,T>
    {
    public:
        static T result(T *a,T*b)
        {
            return (*a) * (*b);
        }
    };
    
    
    int main()
    
    {
        float a[3] = {1,2,3};
        float b[3] = {1,2,3};
        std::cout << DotProduct<3,float>::result(a,b) << std::endl;
        return 0;
    }
    View Code

    (2)求数组合和数组乘积Accumulate

    enum Accumulate_Type
    {
        ADD,
        Mutiply,
    };
    
    
    template <int N,typename T,Accumulate_Type Type=ADD>
    class Accumulate
    {
    public:
        static T result(T *data)
        {
            if(Type == Accumulate_Type::ADD)
                return *data + Accumulate<N-1,T,Type>::result(data+1);
            return *data * Accumulate<N-1,T,Type>::result(data+1);
        }
    };
    
    template <typename T,Accumulate_Type Type>
    class Accumulate<1,T,Type>
    {
    public:
        static T result(T *data)
        {
            return *data;
        }
    };
    
    void testAccumulate()
    {
        float a[3] = {3,2,3};
        std::cout << "Mutiply:"<<Accumulate<3,float,Accumulate_Type::Mutiply>::result(a)<<std::endl;
        std::cout << "Add:"    <<Accumulate<3,float,Accumulate_Type::ADD>::result(a)<<std::endl;
    }
    View Code

    表达式模版:

     一个疑问点:一个简单的模版类:

     下面两种方案都一样:  

    Simple<T>& operator= (Simple<T> const &b)
        {
            std::cout << "operator= " << "a:" << this << "b:" <<&b <<std::endl;
            val = b.val;
        }
    Simple& operator= (Simple const &b)
        {
            std::cout << "operator= " << "a:" << this << " b:" <<&b <<std::endl;
            val = b.val;
        }

    类定义全部定义:

    template <typename T>
    class Simple
    {
    public:
        T val;
    
    
        Simple(T m):val(m)
        {
    
        }
    
        /*
        Simple<T>& operator= (Simple<T> const &b)
        {
            std::cout << "operator= " << "a:" << this << "b:" <<&b <<std::endl;
            val = b.val;
        }
        */
    
    
        Simple& operator= (Simple const &b)
        {
            std::cout << "operator= " << "a:" << this << " b:" <<&b <<std::endl;
            val = b.val;
        }
    
        void debug()
        {
            std::cout << "value :" << val <<std::endl;
        }
    };
    
    
    int main() 
    {
        Simple<int> a(10);
        Simple<int> b(11);
        a = b;
        a.debug();
        return 0;
    }
    View Code

    结果:

    A:0x22fe40
    B:0x22fe30
    operator= a:0x22fe40 b:0x22fe30
    value :11

    如何修改函数对象的内容通过for_each()

    #include <iostream>
    #include <algorithm>
    #include <map>
    #include <cmath>
    using namespace std;
    
    template <typename T>
    class init_map
    {
    public:
        void operator()(const T &rh){
            m[m.size()] = rh;
        }
        T operator[](const int i)
        {
            return (*(m.find(i))).second;
        }
    
        friend ostream& operator<<(ostream &os, init_map <T>&v)
        {
            for(auto iter=v.m.begin(); iter!= v.m.end();iter++)
            {
                cout << (*iter).second <<endl;
            }
    
            return os;
        }
    
    private:
        map<int ,T> m;
    };
    
    
    int main()
    {
        float f[] = {1.1f ,2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1f, 8.1f ,9.1f};
        int counts = floor(sizeof(f)/sizeof(float));
        init_map <float> mv;
    
        // make a function that point to your init_map object
        auto func = [&mv](float v){
            mv(v);
        };
    
        for_each(f,f+counts,func);
        cout << mv;
    
        return 0;
    }
    View Code

    ....

  • 相关阅读:
    airflow 安装问题
    ACM-单词接龙
    ACM-AK吧!少年
    ACM-Alice and Bob
    ACM-Satellite Photographs
    ACM-Subset sum
    ACM-Special Array
    数据挖掘-回归分析
    数据库原理-数据库系统的结构
    数据库原理-几种数据模型
  • 原文地址:https://www.cnblogs.com/gearslogy/p/5643805.html
Copyright © 2011-2022 走看看