Online Book Reader

Home Category

Professional C__ - Marc Gregoire [336]

By Root 1564 0

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::setElementAt(size_t x, size_t y, const T& inElem)

{

mCells[x][y] = inElem;

}

template

T& Grid::getElementAt(size_t x, size_t y)

{

return mCells[x][y];

}

template

const T& Grid::getElementAt(size_t x, size_t y) const

{

return mCells[x][y];

}

Code snippet from GridNonType\Grid.h

Note that wherever you previously specified Grid you must now specify Grid to represent the three template parameters.

You can instantiate this template and use it like this:

Grid myGrid;

Grid anotherGrid;

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 testGrid; // DOES NOT COMPILE

However, if you make height const, it compiles:

const size_t height = 10;

Grid testGrid; // compiles and works

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 and Grid are two different types. You can’t assign an object of one type to an object of the other, and variables of one type can’t be passed to functions or methods that expect variables of another type.

Non-type template parameters become part of the type specification of instantiated objects.

Default Values for Non-Type Parameters

If you

Return Main Page Previous Page Next Page

®Online Book Reader