C++ template

 
####################### 
###    template    #### 
####################### 
 
(1) function template 
(2) class template 
(3) member function template 
(4) input paramter template 
(5) template specialization 
 
 
############################### 
###    function template    ### 
############################### 
 
### template/typename/class 
 
imagine you have many similar overload functions defined. 
 
void display (vector<int>&); 
void display (vector<double>&); 
void display (vector<string>&); 
 
==> you will have pretty much the duplicate definitions for each of them. 
==> use template to simplify. 
 
// T is just a random word, it can be anything. e.g. T, elemType, foobar, etc 
----------- 
template <typename T> void display(vector<T> &vec){ 
     for (int i = 0; i < vec.size() ; i++) 
     { 
        T t = vec[i]; 
        cout << t << ' '; 
     } 

---------- 
instead of "typename" you can use "class" 
 
 
=======>  template function when used together with "inline", you can reduce the dependency on #define macro. 
 
---- syntax ------------------------------------------------------------------------ 
#define maxro_name(input parameter) (actual operation you want the macro to perform) 
------------------------------------------------------------------------------------ 
 
e.g. 
#define ADDITION(a,b) (a+b) 
#define MAX(a,b) ((a) > (b) ? (a) : (b)) 
 
template<typename T> inline T max(const T& a, const T& b) 

  return ( a > b ) ? (a) : (b); 

 
(ref) 
http://www.geocities.jp/ky_webid/cpp/language/026.html 
http://www.geocities.jp/ky_webid/ProgrammingPlacePlus/c/028.html 
 
 
 
########################################################## 
###      class template, member function template      ### 
########################################################## 
 
e.g. 
----------------------------------------------- 
#include <iostream> 
#include <string> 
using namespace std; 
 
template <typename T, typename Z> class CParent 

public: 
  CParent() : var(0),name(0){} 
  CParent( T x, Z z ) { var = x ; name = z;} 
  T getvar(){ return var;} 
  Z getname(){ return name;} 
  template <typename U> U returnInput(const U& u){return u;} 
private: 
  T var; 
  Z name; 
}; 
 
int main() 

  CParent<int,string> cp(123, "halo");            //  T = int, Z = string 
  cout << cp.getvar() << endl; 
  cout << cp.getname() << endl; 
  cout << cp.returnInput(0.567) << endl;          //  U = double 
 
  CParent<int,string>* pcp1 = new CParent<int,string>;                // if using pointer, this is how you declare. 
  CParent<int,string>* pcp2 = new CParent<int,string>(222,"foobar");  // calls the second constructor 
 
  return 0; 

---------------------------------------------- 
 
 
(ref) 
http://yukki99.studio-web.net/stage/cpp_1-10.html 
 
 
###### 
######   tricky BAD example 
###### 
 
 
=======>  template initial declaration & definition must exist in the same file. 
=======>  below example will NOT compile because compile happens on file basis. main.cpp compiles based on the declaration in tmp.h ( we get main.obj ) 
=======>  tmp.cpp compiles also. but no instantiation of any of the functions because none is used within tmp.cpp ( we get tmp.obj ) 
=======>  main.obj goes look for the instance of template functions but none. error. 
 
BAD example ( compile error ) 
---------------------------------------------   // tmp.h 
template <typename T> class CParent 

 public: 
  CParent( T x ); 
  T getvar(); 
  template<typename U> U returnInput(const U& u); 
 private: 
  T var; 
}; 
 
---------------------------------------------   // tmp.cpp 
#include "tmp.h" 
#include <iostream> 
using namespace std; 
 
template<typename T> CParent<T>::CParent( T x ) 

  var = x ; 

 
template<typename T> T CParent<T>::getvar() 

  return var; 

 
template<typename U> template<typename T> U CParent<T>::returnInput(const U& u) 

  return u; 

 
---------------------------------------------   // main.cpp 
#include <iostream> 
#include "tmp.h" 
using namespace std; 
 
int main() 

  CParent<int> cp(123); 
  cout << cp.getvar() << endl; 
  cout << cp.returnInput(0.567) << endl; 
 
  return 0; 

 
--------------------------------------------- 
 
 
###### 
######  GOOD example 
###### 
 
==============> there are ways to get aounrd this, such as 
- help instantiate by explicitly instantiating by  template int getvar();   // but this defeates the purpose of template concept 
- by #include "tmp.cpp" within "tmp.h"    but it's a hack. 
 
==============> thus, as a general rule, just write template definition in the same header file where you declare originally. 
 
GOOD example 
--------------------------------------------  // tmp.h 
template <typename T> class CParent 

 public: 
  CParent( T x ); 
  T getvar(); 
  template<typename U> U returnInput(const U& u); 
 private: 
  T var; 
}; 
 
template<typename T> CParent<T>::CParent( T x ) 

  var = x ; 

 
template<typename T> T CParent<T>::getvar() 

  return var; 

 
template<typename T> template<typename U> U CParent<T>::returnInput(const U& u) 

  return u; 

 
--------------------------------------------  // main.cpp 
#include <iostream> 
#include "tmp.h" 
using namespace std; 
 
int main() 

  CParent<int> cp(123); 
  cout << cp.getvar() << endl; 
  cout << cp.returnInput(0.567) << endl; 
 
  return 0; 

-------------------------------------------- 
 
 
==========>  further re-writing tmp.h as below 
 
------------------------------------------------------------   // tmp.h 
template <typename T> class CParent 

 public: 
  CParent( T x ) { var = x;} 
  T getvar(){ return var;} 
  template<typename U> U returnInput(const U& u) {return u;} 
 private: 
  T var; 
}; 
 
------------------------------------------------------------ 
 
=====>  notice how much "simpler" if you can define member functions inside class definition. 
=====>  you dont have to rewrite template<typename T> and CParent<T>:: class scope every time you define member func. 
 
e.g. 
------------------------ 
T getvar(){ return var;} 
------------------------ 
or 
--------------------------------------------------------- 
template<typename T> T CParent<T>::getvar(){ return var;} 
--------------------------------------------------------- 
 
 
 
(ref) 
http://www.skpme.com/cpp/cpp_template_class.shtml 
http://d.hatena.ne.jp/pknight/20090826/1251303641 
http://www.kab-studio.biz/Programing/Codian/Cpp/02.html 
http://msdn.microsoft.com/ja-jp/library/swta9c6e.aspx 
http://msdn.microsoft.com/ja-jp/library/80dx1bas.aspx 
 
 
 
####################################### 
####   template input parameter    #### 
####################################### 
 
you can specify an actual data type within the template spec. 
 
e.g. 
---------------------------------------------- 
#include <iostream> 
using namespace std; 
 
template <typename T, int size> class CParent      // see here 

public: 
  CParent(){ 
    for(int i =0; i<size ;i++){ 
      arr[i] = i; 
    } 
  } 
  void print(){ 
    for(int i =0; i<size ;i++){ 
      cout << arr[i] << ' '; 
    } 
    cout << endl; 
  } 
private: 
  T arr[size]; 
}; 
 
int main() 

  CParent<int, 15> cp;                             // see here 
  cp.print();                                      // print 0 to 14 
 
  int foo = 10; 
  const int bar = 10; 
 
  CParent<int, foo> cp2;                           // error 
  CParent<int, bar> cp3;                           // ok 
 
  return 0; 

 
---------------------------------------------- 
 
 
 
######################################################## 
###    default value for input parameter template    ### 
######################################################## 
 
you can set a default value to template input paramter ONLY for template class. NOT for template function. 
but, the paramter with the default argument MUST come after the parameters without default arg. 
 
 
e.g. 
----------------------------------------------------- 
 
template <typename T, int size = 123> class CParent {}; 
//template <int size = 123, typename T> class CParent {};   //  compile error 
 
int main() 

CParent<string> cp;                               // the second paramter can be omitted. 
 // CParent<,string> cp1;                             // never works 
 
return 0; 

----------------------------------------------------- 
 
 
##################################### 
###    template specialization    ### 
##################################### 
 
(1) class 
 
template lets you define function/class with transparency on data types. but suppose if you want to define differently only for "int". 
 
NOTE:  generic definition must come BEFORE the specialized ones 
 
e.g. 
------------------------------------------ 
#include <iostream> 
using namespace std; 
 
template <typename T> class CParent 

public: 
  CParent(){ cout << "generic template"<< endl;} 
}; 
 
template <> class CParent<int>                                // look here for the syntax 

public: 
  CParent(){ cout << "specialized template for int" << endl;} 
}; 
 
int main() 

  CParent<char> cp0;                       // print "generic template" 
  CParent<int> cp1;                        // print "specialized template for int" 
  return 0; 

 
------------------------------------------ 
 
 
 
(2) function 
 
smiliar. see below for the syntax. 
 
template <typename T> void func(T t);      //  generic version 
template <> void func<int>(int i);         //  int specialized version 
template <> void func(int i);              //  int specialized version (alternative & simplified way) 
 
 
 
(3) partial template specialization 
 
this is kinda between a generic template and a specialized template. 
(legacy compiler may not handle this.) 
 
 
e.g. 
------------------------------------------ 
#include <iostream> 
using namespace std; 
 
template <typename T> class CParent 

public: 
  CParent(){ cout << "generic template"<< endl;} 
}; 
 
template <typename T> class CParent<T*> 

public: 
  CParent(){ cout << "partially specialized template for pointers" << endl;} 
}; 
 
int main() 

  CParent<char> cp0;                       // print "generic template" 
  CParent<char*> cp1;                      // print "partially specialized template for pointers" 
  return 0; 

------------------------------------------ 
 

  1. 2014-05-27 00:08:09 |
  2. Category : cpp
  3. Page View:

Google Ads