//: C05:DelayedInstantiation.cpp // Member functions of class templates are not // instantiated until they're needed. class X { public: void f() {} }; class Y { public: void g() {} }; template<typename T> class Z { T t; public: void a() { t.f(); } void b() { t.g(); } }; int main() { Z<X> zx; zx.a(); // Doesn't create Z<X>::b() Z<Y> zy; zy.b(); // Doesn't create Z<Y>::a() } ///:~
Listado 6.31. C05/DelayedInstantiation.cpp
//: C05:Nobloat.h // Shares code for storing pointers in a Stack. #ifndef NOBLOAT_H #define NOBLOAT_H #include <cassert> #include <cstddef> #include <cstring> // The primary template template<class T> class Stack { T* data; std::size_t count; std::size_t capacity; enum { INIT = 5 }; public: Stack() { count = 0; capacity = INIT; data = new T[INIT]; } void push(const T& t) { if(count == capacity) { // Grow array store std::size_t newCapacity = 2 * capacity; T* newData = new T[newCapacity]; for(size_t i = 0; i < count; ++i) newData[i] = data[i]; delete [] data; data = newData; capacity = newCapacity; } assert(count < capacity); data[count++] = t; } void pop() { assert(count > 0); --count; } T top() const { assert(count > 0); return data[count-1]; } std::size_t size() const { return count; } }; // Full specialization for void* template<> class Stack<void *> { void** data; std::size_t count; std::size_t capacity; enum { INIT = 5 }; public: Stack() { count = 0; capacity = INIT; data = new void*[INIT]; } void push(void* const & t) { if(count == capacity) { std::size_t newCapacity = 2*capacity; void** newData = new void*[newCapacity]; std::memcpy(newData, data, count*sizeof(void*)); delete [] data; data = newData; capacity = newCapacity; } assert(count < capacity); data[count++] = t; } void pop() { assert(count > 0); --count; } void* top() const { assert(count > 0); return data[count-1]; } std::size_t size() const { return count; } }; // Partial specialization for other pointer types template<class T> class Stack<T*> : private Stack<void *> { typedef Stack<void *> Base; public: void push(T* const & t) { Base::push(t); } void pop() {Base::pop();} T* top() const { return static_cast<T*>(Base::top()); } std::size_t size() { return Base::size(); } }; #endif // NOBLOAT_H ///:~
Listado 6.32. C05/Nobloat.h
//: C05:NobloatTest.cpp #include <iostream> #include <string> #include "Nobloat.h" using namespace std; template<class StackType> void emptyTheStack(StackType& stk) { while(stk.size() > 0) { cout << stk.top() << endl; stk.pop(); } } // An overload for emptyTheStack (not a specialization!) template<class T> void emptyTheStack(Stack<T*>& stk) { while(stk.size() > 0) { cout << *stk.top() << endl; stk.pop(); } } int main() { Stack<int> s1; s1.push(1); s1.push(2); emptyTheStack(s1); Stack<int *> s2; int i = 3; int j = 4; s2.push(&i); s2.push(&j); emptyTheStack(s2); } ///:~
Listado 6.33. C05/NobloatTest.cpp