Professional C__ - Marc Gregoire [346]
Here is the constructor definition. It assumes that the Container type has a resize() method. If you try to instantiate this template by specifying a type that has no resize() method, the compiler will generate an error:
template Grid mWidth(inWidth), mHeight(inHeight) { // Dynamically allocate the array of mWidth containers mCells = new Container[mWidth]; for (size_t i = 0; i < mWidth; i++) { // Resize each container so that it can hold mHeight elements. mCells[i].resize(mHeight); } } Code snippet from GridTemplateContainer\Grid.h Here is the destructor definition. There’s only one call to new in the constructor, so only one call to delete in the destructor. template Grid { delete [] mCells; mCells = nullptr; } Code snippet from GridTemplateContainer\Grid.h The code in copyFrom() assumes that you can access elements in the container by using array [] notation. Chapter 18 explains how to overload the [] operator to implement this feature in your own container classes. Both vector and deque from the STL support this syntax. template void Grid { mWidth = src.mWidth; mHeight = src.mHeight; mCells = new Container[mWidth]; for (size_t i = 0; i < mWidth; i++) { // Resize each element, as in the constructor. mCells[i].resize(mHeight); } for (size_t i = 0; i < mWidth; i++) { for (size_t j = 0; j < mHeight; j++) { mCells[i][j] = src.mCells[i][j]; } } } Code snippet from GridTemplateContainer\Grid.h Here are the implementations of the remaining methods: template Grid { copyFrom(src); } template Grid { // Check for self-assignment. if (this == &rhs) { return *this; } // Free the old memory. delete [] mCells; mCells = nullptr; // Copy the new memory. copyFrom(rhs); return *this; } 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 GridTemplateContainer\Grid.h Now you can instantiate and use Grid objects like this: Grid Grid myIntGrid.setElementAt(3, 4, 5); cout << myIntGrid.getElementAt(3, 4); Grid grid2 = myIntGrid; Code snippet from GridTemplateContainer\GridTest.cpp The use of the word Container for the parameter name doesn’t mean that the type really must be a container. You could try to instantiate the Grid class with an int instead: Grid This line will not compile, but it might not give you the error you expect. It won’t complain that the second type argument is an int instead of a container. Instead it will tell you that left of '.resize' must have class/struct/union type. That’s because the compiler attempts to generate a Grid class with int as the Container. Everything works fine until it tries to compile this line: mCells[i].resize(mHeight); At that point, the compiler realizes that mCells[i] is an int, so you can’t call the resize() method on it. This approach is used in