Template Basics


Using template syntax, we can create an Array class that is parameterized on any number of parameters, including the type of data to manage and how large the internal buffer should be:

[View full width]

template <typename[1] T, size_t MAX_ELEMS> class Array { public: T& operator[](size_t n) { if( n < 0 || n >= MAX_ELEMS ) throw "out of bounds!"; return m_rg[n]; } protected: T m_rg[MAX_ELEMS]; };


[1] The ANSI C++ Standard allows the use of the keyword class instead of the keyword typename, but the use of class is deprecated.

Notice that the only difference in this code is the use of the template statement before the class declaration. When the compiler sees a template, it knows to store the class declaration in its internal data structures, but not to generate any code. The compiler can't generate the code until it sees how the client would like to use it:

struct Point { long x; long y; }; void main(int argc, char* argv[]) {   Array<long, 8> a1;   // Array of 8 longs   Array<char, 256> a2; // Array of 256 chars   Array<Point, 16> a3; // Array of 16 Points   ... } 


The compiler uses the client's template parameters to generate the code for the class on demand, effectively creating a new member of the Array family of classes with each use.[2] Because the compiler is using the template parameters to generate the code, only parameters whose values are known at compile time are allowed. However, that includes built-in types, user-defined types, constants, and even function pointers. To make the template even more convenient for the client to use, you're allowed to declare default values for template parameters, just as you would for functions:

[2] The linker makes sure that only one expansion per set of template parameters actually makes in into the final image.

template <typename T, size_t MAX_ELEMS = 8> class Array {...}; void main(int argc, char* argv[]) {   Array<long>      a1; // Array of 8 longs   Array<char, 256> a2; // Array of 256 chars   ... } 


Template Specialization

You might decide that for a specific combination of template parameters, the generic template expansion isn't good enough. For example, if you decide that an Array of 256 characters should have an equality operator, you might decide to override the Array general template using the template specialization syntax:

template <> // No template arguments here class Array<char, 256> { // Template argument values here public:   // You are not required to provide the same functionality   // as the general template (although it's a good idea)   char& operator[](size_t n) {     if( n < 0 || n >= 256 ) throw "out of bounds!";     return m_sz[n];   }   // You may add functionality not in the general template   bool operator==(const Array<char, 256>& rhs) {     return strcmp(m_sz, rhs.m_sz);   } protected:   char m_sz[256]; }; 


The client doesn't have to do anything new to use the specialized version of the template. When the compiler sees Array<char, 256>, the client automatically gets the specialized version.

Templates as Base Classes

Template specialization allows the addition of new functionality and optimized implementations based on specific template parameters. For example, the specialization I just showed specializes on all the parameters, both the type and the size of the array. It would probably be more useful to be able to specialize on the type of data held, but to expose additional functions for character strings of any size. This can be accomplished by using the Array as a base class:

template <size_t MAX_LEN> class String : public Array<char, MAX_LEN+1> { public:   // Additional functionality   bool operator==(const String<MAX_LEN>& rhs) {     return strcmp(m_rg, rhs.m_rg);   } }; 


Notice that the String is still parameterized on length and that it passes arguments to the base Array class. The type is fixed because we're building a string, but the number of elements to store is based on the String template argument. In effect, this achieves a partial specialization, although the client code must use the String template instead of the Array template to make use of it.




ATL Internals. Working with ATL 8
ATL Internals: Working with ATL 8 (2nd Edition)
ISBN: 0321159624
EAN: 2147483647
Year: 2004
Pages: 172

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net