template template class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
This is a note I made after revisiting template template class. Hope it helps others out there too. 

Here goes the code:


#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;
}
Last edited on
Please use code tags when posting code, to make it readable.
your terminology is a bit off, so it's difficult to follow.

There are three kinds of template parameters: non-type, type, and template. Your takeAny is a template with one type template parameter: it requires a type (not a value, not a template) to be instantiated. Your takeTC_Only is a template with one template template parameter, it requires a template (not a value, not a type) to be instantiated.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Thanks for a good summary. 


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 
{
};
Last edited on
Topic archived. No new replies allowed.