AlgebraMaster

Modern C++ 创造非凡 . 改变世界

导航

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\n");
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\n");
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\n\n";
    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\n";
    }
};

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\n";
    }
};

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\n";
}
// 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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.

posted on 2015-02-10 10:34  gearslogy  阅读(544)  评论(0编辑  收藏  举报