zoukankan      html  css  js  c++  java
  • C++ Template 编程,泛型编程练习

     1 #include <iostream>
     2 #include <string>
     3 #include <deque>
     4 #include <stdexcept>
     5 template <typename T>
     6 class my_stack
     7 {
     8 private:
     9     std::deque<T> elems;
    10 public:
    11     void push(T const &);
    12     void pop();
    13     T top()const;
    14     bool empty()const{return elems.empty();}
    15     //operator = 
    16     template <typename T2>
    17     my_stack<T> & operator=(my_stack<T2> const&);
    18 };
    19 
    20 template <typename T>
    21 void my_stack<T>::push(T const &elem)
    22 {
    23     elems.push_back(elem);
    24 }
    25 
    26 template <typename T>
    27 void my_stack<T>::pop()
    28 {
    29     if (this->empty())
    30     {
    31         throw std::out_of_range("the list is empty,please insert the elems
    ");
    32     }
    33     elems.pop_back();
    34 }
    35 template <typename T>
    36 T my_stack<T>::top()const
    37 {
    38     if(this->empty())
    39     {
    40         throw std::out_of_range("No elements
    ");
    41 
    42     }
    43     return elems.back();
    44 }
    45 template <typename T>
    46 template <typename T2>
    47 my_stack<T>& my_stack<T>::operator=(my_stack<T2> const&op2)
    48 {
    49     if( (void*)this == (void *)&op2)
    50     {
    51         return *this;
    52     }
    53     my_stack<T2> tmp(op2);   //copy constructor
    54     elems.clear();
    55     while(!tmp.empty())
    56     {
    57         elems.push_front(tmp.top());  //put in the front !...
    58         tmp,pop();    // while loop breakdown
    59     }
    60     return *this;
    61 }
    62 
    63 int main()
    64 {
    65     my_stack <int> int_stack;
    66     my_stack <float> float_stack;
    67 
    68     float_stack = int_stack;
    69     
    70     return 0;
    71 }

    <2> 模板作为模板的参数:

    //
    // Created by Administrator on 2017/5/7.
    //
    
    #ifndef TASARG_TEMPPARM_H
    #define TASARG_TEMPPARM_H
    
    #include <iostream>
    ///Value handle define here
    template <typename T>
    class GLY_handle
    {
    public:
        GLY_handle();
        T getValue() const ;
        void setValue( T data) ;
    
    private:
        T mValue;
    };
    
    template <typename T>
    GLY_handle<T>::GLY_handle()
    {
    }
    template <typename T>
    T GLY_handle<T>::getValue() const {
        return mValue;
    }
    template  <typename T>
    void GLY_handle<T>::setValue(T data) {
        mValue = data;
    }
    
    
    /// ----------------------GLY MAP----------------------------------------------
    /// Ting is template class can handle value
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    class GLY_Map
    {
    public:
        /// default
        GLY_Map();
    
        /// copy function
        GLY_Map(const GLY_Map<Ting,KeyT,ValueT>&);
    
        /// getMethod
        KeyT first() const;
        ValueT second() const;
        /// setMethod
        void setMapValue(KeyT key,ValueT data);
    
    
        /// dataHandle
        Ting<KeyT> &firstHandle() ;
        Ting<ValueT> &secondHandle();
    
    private:
        Ting <KeyT> mKey;
        Ting <ValueT> mValue;
    };
    
    template <template <typename T> class Ting,typename KeyT,typename  ValueT>
    GLY_Map<Ting,KeyT,ValueT>::GLY_Map()
    {
    
    }
    /// GLY_MAP copy function define here
    template <template <typename T> class Ting,typename KeyT,typename  ValueT>
    GLY_Map<Ting,KeyT,ValueT>::GLY_Map(const GLY_Map<Ting, KeyT, ValueT> & rhs)
    {
        // copy function
        mKey = rhs.mKey;
        mValue = rhs.mValue;
    }
    
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    KeyT GLY_Map<Ting,KeyT,ValueT>::first() const
    {
        return mKey.getValue();
    }
    
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    ValueT GLY_Map<Ting,KeyT,ValueT>::second() const
    {
        return mValue.getValue();
    }
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    void GLY_Map<Ting,KeyT,ValueT>::setMapValue(KeyT key, ValueT data)
    {
        mKey.setValue(key);
        mValue.setValue(data);
    }
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    Ting<KeyT> & GLY_Map<Ting,KeyT,ValueT>::firstHandle()
    {
        return mKey;
    }
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    Ting<ValueT> &GLY_Map<Ting,KeyT,ValueT>::secondHandle()
    {
        return mValue;
    }
    // Operator for std::cout
    template <template <typename T> class Ting,typename KeyT,typename ValueT>
    std::ostream &operator<<(std::ostream &os ,const GLY_Map<Ting,KeyT,ValueT> &data)
    {
        os << "Data key " <<data.first() <<"," << data.second();
        return os;
    };
    
    
    #endif //TASARG_TEMPPARM_H
    tempparm.h
    #include <iostream>
    #include "tempparm.h"
    #include <vector>
    
    
    int main()
    {
        GLY_Map <GLY_handle,std::string,int> testMap;
        testMap.setMapValue("houdini",10);
        std::cout << testMap <<std::endl;
        return 0;
    }
    main.cpp

    <3>  默认模板参数:

    template<class T1,class T2 = int>

    class Topo{...}

    Topo<double,double> T2 //as double

    Topo<double>T2 //as int

    <4> 显示具体化模板:

    #include <iostream>
    template <typename T>
    class GLY_Handle
    {
    public:
        T var;
        void printData()
        {
            std::cout << "print as generic type " << var <<std::endl;
        }
    };
    
    /// explicit the int type
    template <>
    class GLY_Handle<int>
    {
    public:
        void printData()
        {
            std::cout << "print as int type " << var <<std::endl;
        }
        int var;
    };
    
    template <>
    class GLY_Handle<float>
    {
    public:
        void printData()
        {
            std::cout << "print as float type " <<var <<std::endl;
        }
        float var;
    };
    
    
    
    int main()
    {
        GLY_Handle<int> var1;
        var1.var = 10;
        var1.printData();
    
        GLY_Handle<double> var2;
        var2.var = 10.0;
        var2.printData();
    
        GLY_Handle<float> var3;
        var3.var = 10.0f;
        var3.printData();
        return 0;
    }
    View Code

     

    <5> 部分具体化模板:

    <6>模板和友元函数,以及静态成员分配:

    #include <iostream>
    template <typename T>
    class HasFriend
    {
    public:
        HasFriend(const T & i):item(i) { ct++; }
        ~HasFriend() { ct--; }
        friend void counts();
        friend void reports(HasFriend<T> &);
    private:
        T item;
        static int ct;
    };
    /// each specialization has its own static data member
    template <typename T>
    int HasFriend<T>::ct = 0;
    void counts()
    {
        std::cout << "int count " << HasFriend<int>::ct <<std::endl;
        std::cout << "double count " <<HasFriend<double>::ct <<std::endl;
    }
    /// non-template friend to HasFriend<int> class
    void reports(HasFriend <int> &pt) {
        // 为什么能访问pt的私有函数,因为reports函数是在public接口上。
        std::cout << "HasFriend<int>: " <<pt.item <<std::endl;
    }
    /// non-template friend to HasFriend<double> class
    void reports(HasFriend <double> &pt) {
        // 为什么能访问pt的私有函数,因为reports函数是在public接口上。
        std::cout << "HasFriend<double>: " <<pt.item <<std::endl;
    }
    int main()
    {
        counts();
        HasFriend<int> i_01(1);
        HasFriend<int> i_02(10);
        HasFriend<double> d_03(10.00);
    
        std::cout << "After i_01,i_02,d_03 declared
    
    ";
        counts();
    
        reports(i_01);
        reports(i_02);
        reports(d_03);
    
        return 0;
    }
    View Code

    ./out

    int count 0
    double count 0
    After i_01,i_02,d_03 declared

    int count 2
    double count 1
    HasFriend<int>: 1
    HasFriend<int>: 10
    HasFriend<double>: 10

    <7>重载函数模版问题:  

    #include <iostream>
    template <typename T>
    int func(T)      // first
    {
        return 1;
    }
    
    template <typename T>
    int func(T*)    //
    {
        return 2;
    }
    
    
    
    int main()
    {
        std::cout << func(5)        <<std::endl;          // 1
        std::cout << func<int>(5)   <<std::endl;          // 1
        std::cout << func((int*)5)  <<std::endl;          // 2,T=int ,arg is int*
    
        // will create this function func<int*>(int*),
        // and will create  func<int*>(int**),because the second template function
        // but (int*)5 is int* , so will match func<int*>((int*)) better
        std::cout << func<int*>((int*)5)  <<std::endl;   //-> func<int*>(int*)
    
        std::cout << func<int> ((int*)5)  <<std::endl;   // 2,T=int  ,  but arg is int* ->T*
    
        return 0;
    }

    结果:

    1
    1
    2
    1
    2

    <8>explicit specialization(深入显式特化)

    显式特化不一定非得特化类,才能特化类中内容。例如下面,类Outer<void>就没特化出来,但是成员函数和一个静态变量被特化

    也就是说把泛型定义的Outer里的函数和静态变量给替换了

    #include <iostream>
    
    using std::cout;
    using std::endl;
    
    template<typename T>
    class Outer {
    public:
        template<typename U>
        class Inner {
        private:
            static int count;
        };
    
        static int code;
    
        void print() const {
            cout << "generic
    ";
        }
    };
    
    template <typename T>
    int Outer<T>::code = 6;
    
    template <typename T>
    template <typename U>
    int Outer<T>::Inner<U>::count =7;
    
    
    template <>
    class Outer<bool>
    {
    public:
        template <typename U>
        class Inner
        {
        private:
            static int count;
        };
    
        static int code;
        void print() const {
            cout << " bool trait
    ";
        }
    };
    
    template <>
    int Outer<bool>::code = 1;
    
    
    // part of Outer<void> Specialization , but not have "Outer class definition"
    template <>
    int Outer<void>::code = 12;
    
    template <>
    void Outer<void>::print() const {
        cout << "void trait
    ";
    }
    // part of Outer<void> Specialization , but not have "Outer class definition"
    
    
    
    
    int main()
    {
        Outer<bool> val;
        val.print();
    
        cout << Outer<bool>::code <<endl;
        return 0;
    }
    View Code

     <9> typedef 

    std::list 作为模版实参进去第二个默认参数的问题。所以std::list是不能作为默认模版的模版参数.

    (1)即使我们用了typedef

    template <typename T>
    typedef list<T> MyList;
    
    
    template <typename T1, typename T2,
            template <typename> class Container>
    class MapList
    {
    public:
        Container<T1> &First()
        {
            return mFirstList;
        }
        Container<T1> &Scend()
        {
            return mSecondList;
        }
    private:
        Container<T1> mFirstList;
        Container<T2> mSecondList;
    };
    
    
    int main()
    {
    
        MapList<string,int,MyList> list_01;
    }
    View Code

    (2) C++11 ,decltype暴力用法

    template <typename T1,typename T2>
    ??? operator+ (vector<T1> &x,vector<T2> &y)

     对于这样的问题如何返回正确的vector<???>

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    template <typename T1,typename T2>
    auto operator+ (vector<T1> &x,vector<T2> &y) -> vector<decltype(x[0]+y[0])>
    {
        typedef decltype(x[0]+y[0]) types;
        vector<types> temp;
        temp.resize(x.size());
    
        for(int i=0;i<x.size();i++)
        {
            temp[i] = x[i] + y[i];
        }
        return temp;
    };
    
    void unit_test()
    {
        int ttt = 0;
        vector<decltype(ttt)> aaaa ;
        aaaa.resize(5);
        fill(aaaa.begin(),aaaa.end(),5);
        for_each(begin(aaaa),end(aaaa),[](int &val){cout << val <<endl;});
    }
    
    int main()
    {
        vector<int> a;
        vector<float> b;
        a.resize(5);
        b.resize(5);
        fill(a.begin(),a.end(),1);
        fill(b.begin(),b.end(),2);
        auto n = a+b;
        for_each(begin(n),end(n),[&n](decltype(n[0]) &val){cout << val <<endl;});
        return 0;
    }
    View Code

    (3)ElementT类的设计,typedef ,typename实用:

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<initializer_list>
    #include<list>
    #include<stack>
    
    template <typename T>
    T sumOfElements(const std::initializer_list<T> &varList)
    {
        T sum = 0;
        auto func = [&sum,&varList](const T &val)
        {
            sum +=val;
        };
        std::for_each(std::begin(varList),std::end(varList),func);
        return sum;
    }
    
    
    template <typename T>
    typename std::vector<T>::value_type sumOfVector(const std::vector<T> &varList)
    {
        T sum = 0;
        auto func = [&sum,&varList](const T &val)
        {
            sum +=val;
        };
        std::for_each(std::begin(varList),std::end(varList),func);
        return sum;
    }
    
    
    // ElementT Design
    template <typename T>
    class ElementT;
    
    template <typename T>
    class ElementT< std::vector<T> >
    {
    public:
        typedef T TYPE;
    };
    
    template <typename T>
    class ElementT< std::initializer_list<T> >
    {
    public:
        typedef T TYPE;
    };
    
    template <typename T>
    class ElementT< std::stack<T> >
    {
    public:
        typedef T TYPE;
    };
    
    
    template <typename T>
    typename ElementT<T>::TYPE sum_of_elements(T & container)
    {
        typedef typename ElementT<T>::TYPE valType;
        valType sum = valType(0);
        auto func = [&container,&sum](const valType&val)
        {
            sum += val;
        };
        std::for_each(container.begin(),container.end(),func);
        return sum;
    
    }
    
    
    
    
    int main()
    {
        std::cout << "initlist->:"<<sumOfElements({1,2,3,4,5,6}) <<std::endl;
        std::cout << "vector->:  "<<sumOfVector(std::vector<int>{1,2,3,4,5,6}) <<std::endl;
        std::cout <<"ElementT->: "<<sumOfVector(std::vector<int>{1,2,3,4,5,6}) <<std::endl;
        return 0;
    }
    View Code

     <10>

    template<char const*msg>

    class Var{}

    Var<"X"> 和Var<"X">其实是两个不同的实例,但是"X"实际类型是char const[2],传递给模版实参decay "char const *" type.

    .

     <11> 求max(1,2,3,4,3,4,1) 最大值 递归

    template <typename T>
    T const &tmax(const T &a,const T&b)
    {
        cout << "basic:"<< a <<"|"<< b <<endl;
        return a<b?b:a;
    }
    
    template <typename T,typename ...Args>
    T const&tmax(const T&a,const T&b,const Args&... args)
    {
        cout<<"...args" << a <<"|"<< b <<endl;
        return tmax(a,tmax(b,args...));
    };
    
    
    
    int main()
    {
        cout << tmax(3,2,1) ;
        //show_list(1,2,3,4,5);
        return 0;
    }
    View Code

     

    .

  • 相关阅读:
    装箱、拆箱操作发生在
    @Data的注解使用以及在IDEA上安装
    Mysql中 BLOB字段转String的方法
    不属于java语言鲁棒性特点的是
    java object默认的基本方法
    哪个类可用于处理 Unicode?
    类和接口的继承
    抽象类的叙述:
    Hashtable 和 HashMap 的区别是:
    编程之美初赛第一场--焦距
  • 原文地址:https://www.cnblogs.com/gearslogy/p/4283203.html
Copyright © 2011-2022 走看看