template<class T> class Stack { T* data; size_t count; public: void push(const T& t); // Etc. };
Stack<int> myStack; // A Stack of ints
template<class T, size_t N> class Stack { T data[N]; // Fixed capacity is N size_t count; public: void push(const T& t); // Etc. };
Stack<int, 100> myFixedStack;
//: C05:Urand.h {-bor} // Unique randomizer. #ifndef URAND_H #define URAND_H #include <bitset> #include <cstddef> #include <cstdlib> #include <ctime> using std::size_t; using std::bitset; template<size_t UpperBound> class Urand { bitset<UpperBound> used; public: Urand() { srand(time(0)); } // Randomize size_t operator()(); // The "generator" function }; template<size_t UpperBound> inline size_t Urand<UpperBound>::operator()() { if(used.count() == UpperBound) used.reset(); // Start over (clear bitset) size_t newval; while(used[newval = rand() % UpperBound]) ; // Until unique value is found used[newval] = true; return newval; } #endif // URAND_H ///:~
Listado 6.1. C05/Urand.h
//: C05:UrandTest.cpp {-bor} #include <iostream> #include "Urand.h" using namespace std; int main() { Urand<10> u; for(int i = 0; i < 20; ++i) cout << u() << ' '; } ///:~
Listado 6.2. C05/UrandTest.cpp
template<class T, size_t N = 100> class Stack { T data[N]; // Fixed capacity is N size_t count; public: void push(const T& t); // Etc. };
template<class T = int, size_t N = 100> // Both defaulted class Stack { T data[N]; // Fixed capacity is N size_t count; public: void push(const T& t); // Etc. }; Stack<> myStack; // Same as Stack<int, 100>
template<class T, class Allocator = allocator<T> > class vector;
//: C05:FuncDef.cpp #include <iostream> using namespace std; template<class T> T sum(T* b, T* e, T init = T()) { while(b != e) init += *b++; return init; } int main() { int a[] = { 1, 2, 3 }; cout << sum(a, a + sizeof a / sizeof a[0]) << endl; // 6 } ///:~
Listado 6.3. C05/FuncDef.cpp
//: C05:TempTemp.cpp // Illustrates a template template parameter. #include <cstddef> #include <iostream> using namespace std; template<class T> class Array { // A simple, expandable sequence enum { INIT = 10 }; T* data; size_t capacity; size_t count; public: Array() { count = 0; data = new T[capacity = INIT]; } ~Array() { delete [] data; } void push_back(const T& t) { if(count == capacity) { // Grow underlying array size_t newCap = 2 * capacity; T* newData = new T[newCap]; for(size_t i = 0; i < count; ++i) newData[i] = data[i]; delete [] data; data = newData; capacity = newCap; } data[count++] = t; } void pop_back() { if(count > 0) --count; } T* begin() { return data; } T* end() { return data + count; } }; template<class T, template<class> class Seq> class Container { Seq<T> seq; public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { Container<int, Array> container; container.append(1); container.append(2); int* p = container.begin(); while(p != container.end()) cout << *p++ << endl; } ///:~
Listado 6.4. C05/TempTemp.cpp
Seq<T> seq;
template<class T, template<class> class Seq>
template<class T, template<class U> class Seq>
T operator++(int);
//: C05:TempTemp2.cpp // A multi-variate template template parameter. #include <cstddef> #include <iostream> using namespace std; template<class T, size_t N> class Array { T data[N]; size_t count; public: Array() { count = 0; } void push_back(const T& t) { if(count < N) data[count++] = t; } void pop_back() { if(count > 0) --count; } T* begin() { return data; } T* end() { return data + count; } }; template<class T,size_t N,template<class,size_t> class Seq> class Container { Seq<T,N> seq; public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { const size_t N = 10; Container<int, N, Array> container; container.append(1); container.append(2); int* p = container.begin(); while(p != container.end()) cout << *p++ << endl; } ///:~
Listado 6.5. C05/TempTemp2.cpp
//: C05:TempTemp3.cpp {-bor}{-msc} // Template template parameters and default arguments. #include <cstddef> #include <iostream> using namespace std; template<class T, size_t N = 10> // A default argument class Array { T data[N]; size_t count; public: Array() { count = 0; } void push_back(const T& t) { if(count < N) data[count++] = t; } void pop_back() { if(count > 0) --count; } T* begin() { return data; } T* end() { return data + count; } }; template<class T, template<class, size_t = 10> class Seq> class Container { Seq<T> seq; // Default used public: void append(const T& t) { seq.push_back(t); } T* begin() { return seq.begin(); } T* end() { return seq.end(); } }; int main() { Container<int, Array> container; container.append(1); container.append(2); int* p = container.begin(); while(p != container.end()) cout << *p++ << endl; } ///:~
Listado 6.6. C05/TempTemp3.cpp
template<class T, template<class, size_t = 10> class Seq>
//: C05:TempTemp4.cpp {-bor}{-msc} // Passes standard sequences as template arguments. #include <iostream> #include <list> #include <memory> // Declares allocator<T> #include <vector> using namespace std; template<class T, template<class U, class = allocator<U> > class Seq> class Container { Seq<T> seq; // Default of allocator<T> applied implicitly public: void push_back(const T& t) { seq.push_back(t); } typename Seq<T>::iterator begin() { return seq.begin(); } typename Seq<T>::iterator end() { return seq.end(); } }; int main() { // Use a vector Container<int, vector> vContainer; vContainer.push_back(1); vContainer.push_back(2); for(vector<int>::iterator p = vContainer.begin(); p != vContainer.end(); ++p) { cout << *p << endl; } // Use a list Container<int, list> lContainer; lContainer.push_back(3); lContainer.push_back(4); for(list<int>::iterator p2 = lContainer.begin(); p2 != lContainer.end(); ++p2) { cout << *p2 << endl; } } ///:~
Listado 6.7. C05/TempTemp4.cpp
//: C05:TypenamedID.cpp {-bor} // Uses 'typename' as a prefix for nested types. template<class T> class X { // Without typename, you should get an error: typename T::id i; public: void f() { i.g(); } }; class Y { public: class id { public: void g() {} }; }; int main() { X<Y> xy; xy.f(); } ///:~
Listado 6.8. C05/TypenamedID.cpp
//: C05:PrintSeq.cpp {-msc}{-mwcc} // A print function for Standard C++ sequences. #include <iostream> #include <list> #include <memory> #include <vector> using namespace std; template<class T, template<class U, class = allocator<U> > class Seq> void printSeq(Seq<T>& seq) { for(typename Seq<T>::iterator b = seq.begin(); b != seq.end();) cout << *b++ << endl; } int main() { // Process a vector vector<int> v; v.push_back(1); v.push_back(2); printSeq(v); // Process a list list<int> lst; lst.push_back(3); lst.push_back(4); printSeq(lst); } ///:~
Listado 6.9. C05/PrintSeq.cpp
//: C05:DotTemplate.cpp // Illustrate the .template construct. #include <bitset> #include <cstddef> #include <iostream> #include <string> using namespace std; template<class charT, size_t N> basic_string<charT> bitsetToString(const bitset<N>& bs) { return bs. template to_string<charT, char_traits<charT>, allocator<charT> >(); } int main() { bitset<10> bs; bs.set(1); bs.set(5); cout << bs << endl; // 0000100010 string s = bitsetToString<char>(bs); cout << s << endl; // 0000100010 } ///:~
Listado 6.11. C05/DotTemplate.cpp
template<class charT, class traits, class Allocator> basic_string<charT, traits, Allocator> to_string() const;
wstring s = bitsetToString<wchar_t>(bs);
template<typename T> class complex { public: template<class X> complex(const complex<X>&);
complex<float> z(1, 2); complex<double> w(z);
template<typename T> template<typename X> complex<T>::complex(const complex<X>& c) {/* Body here' */}
int data[5] = { 1, 2, 3, 4, 5 }; vector<int> v1(data, data+5); vector<double> v2(v1.begin(), v1.end());
template<class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator());
//: C05:MemberClass.cpp // A member class template. #include <iostream> #include <typeinfo> using namespace std; template<class T> class Outer { public: template<class R> class Inner { public: void f(); }; }; template<class T> template<class R> void Outer<T>::Inner<R>::f() { cout << "Outer == " << typeid(T).name() << endl; cout << "Inner == " << typeid(R).name() << endl; cout << "Full Inner == " << typeid(*this).name() << endl; } int main() { Outer<int>::Inner<bool> inner; inner.f(); } ///:~
Listado 6.12. C05/MemberClass.cpp
Outer == int Inner == bool Full Inner == Outer<int>::Inner<bool>