Online Book Reader

Home Category

Professional C__ - Marc Gregoire [350]

By Root 1510 0

char* getElementAt(size_t x, size_t y) const;

size_t getHeight() const { return HEIGHT; }

size_t getWidth() const { return WIDTH; }

protected:

void copyFrom(const Grid& src);

char* mCells[WIDTH][HEIGHT];

};

Code snippet from GridPartialString\GridString.h

In this case, you are not specializing all the template parameters. Therefore, your template line looks like this:

template

class Grid

Note that the template has only two parameters: WIDTH and HEIGHT. However, you’re writing a Grid class for three arguments: T, WIDTH, and HEIGHT. Thus, your template parameter list contains two parameters, and the explicit Grid contains three arguments. When you instantiate the template, you must still specify three parameters. You can’t instantiate the template with only height and width:

Grid myIntGrid; // Uses the original Grid

Grid myStringGrid; // Uses the partial specialization for char *s

Grid<2, 3> test; // DOES NOT COMPILE! No type specified.

Code snippet from GridPartialString\GridTestString.cpp

Yes, the syntax is confusing. And it gets worse. In partial specializations, unlike in full specializations, you include the template line in front of every method definition:

template

Grid::Grid()

{

for (size_t i = 0; i < WIDTH; i++) {

for (size_t j = 0; j < HEIGHT; j++) {

mCells[i][j] = nullptr; // Initialize each element to nullptr.

}

}

}

Code snippet from GridPartialString\GridString.h

You need this template line with two parameters to show that this method is parameterized on those two parameters. Note that wherever you refer to the full class name, you must use Grid.

You can find the rest of the method definitions in the downloadable source code archive for this book on www.wrox.com.

Another Form of Partial Specialization

The previous example does not show the true power of partial specialization. You can write specialized implementations for a subset of possible types without specializing individual types. For example, you can write a specialization of the Grid class for all pointer types. This specialization might perform deep copies of objects to which pointers point instead of storing shallow copies of the pointers in the grid.

Here is the class definition, assuming that you’re specializing the initial version of the Grid with only one parameter:

#include "Grid.h"

template

class Grid

{

public:

Grid(size_t inWidth = kDefaultWidth,

size_t inHeight = kDefaultHeight);

Grid(const Grid& src);

virtual ~Grid();

Grid& operator=(const Grid& rhs);

void setElementAt(size_t x, size_t y, T* inElem);

T* getElementAt(size_t x, size_t y) const;

size_t getHeight() const { return mHeight; }

size_t getWidth() const { return mWidth; }

static const size_t kDefaultWidth = 10;

static const size_t kDefaultHeight = 10;

protected:

void copyFrom(const Grid& src);

T*** mCells;

size_t mWidth, mHeight;

};

Code snippet from GridPartialPtr\GridPtr.h

As usual, these two lines are the crux of the matter:

template

class Grid

The syntax says that this class is a specialization of the Grid template for all pointer types. At least that’s what it’s telling the compiler. What it’s telling you and me is that the C++ standards committee should have come up with a better syntax. Unless you’ve been working with it for a long time, it’s quite jarring.

You are providing the implementation only in cases where T is a pointer type. Note that if you instantiate a grid like this: Grid myIntGrid, then T will actually be int, not int*. That’s a bit unintuitive, but unfortunately, the way it works. Here is a code example:

Grid myIntGrid; // Uses the non-specialized grid

Grid psGrid(2, 2); // Uses the partial specialization for pointer types

int x = 3, y = 4;

psGrid.setElementAt(0, 0, &x);

psGrid.setElementAt(0, 1, &y);

psGrid.setElementAt(1, 0, &y);

Return Main Page Previous Page Next Page

®Online Book Reader