Professional C__ - Marc Gregoire [336]
This parameter list is similar to the parameter list in a function or method. As in functions and methods, you can write a class with as many template parameters as you want. Additionally, these parameters don’t have to be types, and they can have default values.
Non-Type Template Parameters
Non-type parameters are “normal” parameters such as ints and pointers: the kind of parameters with which you’re familiar from functions and methods. However, non-type template parameters can only be integral types (char, int, long...), enumeration types, pointers and references.
In the Grid template class, you could use non-type template parameters to specify the height and width of the grid instead of specifying them in the constructor. The principle advantage to specifying non-type parameters in the template list instead of in the constructor is that the values are known before the code is compiled. Recall that the compiler generates code for templatized methods by substituting in the template parameters before compiling. Thus, you can use a normal two-dimensional array in your implementation instead of dynamically allocating it. Here is the new class definition:
template class Grid { public: void setElementAt(size_t x, size_t y, const T& inElem); T& getElementAt(size_t x, size_t y); const T& getElementAt(size_t x, size_t y) const; size_t getHeight() const { return HEIGHT; } size_t getWidth() const { return WIDTH; } protected: T mCells[WIDTH][HEIGHT]; }; Code snippet from GridNonType\Grid.h This class is significantly simpler than the old version. Note that the template parameter list requires three parameters: the type of objects stored in the grid and the width and height of the grid. The width and height are used to create a two-dimensional array to store the objects. There is no dynamically allocated memory in the class, so it no longer needs a user-defined copy constructor, destructor, or assignment operator. In fact, you don’t even need to write a default constructor; the compiler generated one is just fine. Here are the class method definitions: template void Grid { mCells[x][y] = inElem; } template T& Grid { return mCells[x][y]; } template const T& Grid { return mCells[x][y]; } Code snippet from GridNonType\Grid.h Note that wherever you previously specified Grid You can instantiate this template and use it like this: Grid Grid myGrid.setElementAt(2, 3, 45); anotherGrid = myGrid; cout << anotherGrid.getElementAt(2, 3); Code snippet from GridNonType\GridTest.cpp This code seems great. Despite the slightly messy syntax for declaring a Grid, the actual Grid code is a lot simpler. Unfortunately, there are more restrictions than you might think at first. First, you can’t use a non-constant integer to specify the height or width. The following code doesn’t compile: size_t height = 10; Grid However, if you make height const, it compiles: const size_t height = 10; Grid A second restriction might be more significant. Now that the width and height are template parameters, they are part of the type of each grid. That means that Grid Non-type template parameters become part of the type specification of instantiated objects. Default Values for Non-Type Parameters If you