http://www.cplusplus.com/forum/general/116769/
#include <iostream>
using namespace std;
/*
* -------------------------------------
* 1. template parameter ( ordinary case )
* -------------------------------------
* template <class C>
* class takeAny
*
* It means:
* takeAny only takes ordinary type, including template class,
* in as its template parameter, less restrictive
*
* -------------------------------------
* -------------------------------------
* 2. template template parameter ( special case I'm talking about today. )
* -------------------------------------
* template <template <class T> class C>
* class takeTC_Only
*
* It means:
* takeTC_Only ONLY takes "template class"
* in as its template parameter, more restrictive
*
* -------------------------------------
*
* We should consider "template <class T> class C" as a whole.
* "T"'s sole purpose is to indicate that "C" is a template class, which
* takeTC_Only expects when doing initialization.
*
* In another word, we can use "C" as a type inside class takeTC_Only to declare variables.
* However when I do so inside class takeTC_Only, I also need to make sure that C is used as template
* class that must be initialized with other specific types, which is a tricky part.
*
* Type "T" could NOT be used inside class takeTC_Only to declare variables.
* Again, its sole purpose is to indicate that "C" is a "template class" and class takeTC_Only
* must take a "template class" as its template class.
* In another word, if we feed class takeTC_Only with an ordinary class, then it will be an error
* because class takeTC_Only only expects a template class to get itself initialized.
*
*/
template <class T>
class aTemplateClass
{
public:
aTemplateClass(T b){a=b;}
void print() const {cout << "data is " << a <<endl;}
T& get(){return a;}
private:
T a;
};
class anOrdinaryClass
{
public:
anOrdinaryClass(int b){a=b;}
void print() const {cout << "data is " << a <<endl;}
int& get(){return a;}
private:
int a;
};
// You can only feed in "a template class" as its template argument when
// initialize takeTC_Only.
template <template <class T> class C>
class takeTC_Only
{
public:
takeTC_Only(C<int> b):a(b) { }
void print() const { a.print();}
private:
// Here is the tricky part: you need use "C" as template class.
// You can NOT do "C<T>& a;" because it doesn't recognize "T" as template parameter.
C<int>& a;
};
// You can either feed in "an ordianry class" OR "a template class" as
// its template argument when initialize takeAny.
template <class C>
class takeAny
{
public:
takeAny(C b):a(b) { }
void print() const { a.print();}
private:
C& a;
};
int main() {
// ##############################################################
// # 1. template class as template parameter : so-called template template class
// ###############################################################
// takeTC_Only MUST take "a Template class" in as its template parameter.
// "aTemplateClass" is a template class so it can be used to initialize takeTC_Only.
aTemplateClass<int> a(3);
// tricky part#2: you don't do "takeTC_Only<aTemplateClass<int> > takeTC(a); ",
// instead, you do "takeTC_Only<aTemplateClass> takeTC(a);"
takeTC_Only<aTemplateClass> takeTC(a);
takeTC.print();
// #######################################
// # 2. any type as template parameter
// #######################################
// template class takeAny takes either an Ordinary class OR a template class in as its template parameter.
// 1. Take an ordinary class as template parameter.
anOrdinaryClass b(3);
takeAny<anOrdinaryClass> take_any(b);
take_any.print();
// 2. Take a template class as template parameter.
takeAny<aTemplateClass<int> > take_any2(a);
take_any2.print();
return 0;
}
Three things a template class can take as template parameter:
1) Type: that are preceded by the class or typename keywords , which represent types. eg: class T 2) Non-Type : regular typed parameters, similar to those found in functions. eg: int N 3) Template : that are preceded by the template keywords , which represent templates. eg: template <class U> class V template <class T, int N, template <class U> class V> class Got_All_Three { };
For example,
Got_All_Three<anOrdinaryClass, 100, aTemplateClass> gat;
or
Got_All_Three<aTemplateClass<int>, 100, aTemplateClass> gat;
No comments:
Post a Comment