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> 模板作为模板的参数:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// // 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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
<3> 默认模板参数:
template<class T1,class T2 = int>
class Topo{...}
Topo<double,double> T2 //as double
Topo<double>T2 //as int
<4> 显示具体化模板:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
<5> 部分具体化模板:
<6>模板和友元函数,以及静态成员分配:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
./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里的函数和静态变量给替换了
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
<9> typedef
std::list 作为模版实参进去第二个默认参数的问题。所以std::list是不能作为默认模版的模版参数.
(1)即使我们用了typedef
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
(2) C++11 ,decltype暴力用法
template <typename T1,typename T2>
??? operator+ (vector<T1> &x,vector<T2> &y)
对于这样的问题如何返回正确的vector<???>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
(3)ElementT类的设计,typedef ,typename实用:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
<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) 最大值 递归
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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; }
.