Online Book Reader

Home Category

Professional C__ - Marc Gregoire [354]

By Root 1514 0
NDGrid& src);

virtual ~NDGrid();

NDGrid& operator=(const NDGrid& rhs);

void resize(size_t newSize);

T& operator[](size_t x);

const T& operator[](size_t x) const;

size_t getSize() const { return mSize; }

static const size_t kDefaultSize = 10;

protected:

void copyFrom(const NDGrid& src);

T* mElems;

size_t mSize;

};

Code snippet from NDGrid\NDGrid.h

Here the recursion ends: The element type is T, not another template instantiation.

The trickiest aspect of the implementations, other than the template recursion itself, is appropriately sizing each dimension of the array. This implementation creates the N-dimensional array with every dimension of equal size. It’s significantly more difficult to specify a separate size for each dimension. However, even with this simplification, there is still a problem: The user should have the ability to create the array with a specified size, such as 20 or 50. Thus, one constructor takes an integer size parameter. However, when you dynamically allocate the nested array of grids, you cannot pass this size value on to the grids because arrays create objects using their default constructor. Thus, you must explicitly call resize() on each grid element of the array. That code follows, with the default and one-argument constructors separated for clarity.

The base case doesn’t need to resize its elements because the elements are Ts, not grids.

Here are the implementations of the main NDGrid template, with highlights showing the differences from the OneDGrid:

template

NDGrid::NDGrid(size_t inSize) : mSize(inSize)

{

mElems = new NDGrid[mSize];

// Allocating the array above calls the 0-argument

// constructor for the NDGrid, which constructs

// it with the default size. Thus, we must explicitly call

// resize() on each of the elements.

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

mElems[i].resize(inSize);

}

}

template

NDGrid::NDGrid() : mSize(kDefaultSize)

{

mElems = new NDGrid[mSize];

}

template

NDGrid::NDGrid(const NDGrid& src)

{

copyFrom(src);

}

template

NDGrid::~NDGrid()

{

delete [] mElems;

mElems = nullptr;

}

template

void NDGrid::copyFrom(const NDGrid& src)

{

mSize = src.mSize;

mElems = new NDGrid[mSize];

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

mElems[i] = src.mElems[i];

}

}

template

NDGrid& NDGrid::operator=(const NDGrid& rhs)

{

// Check for self-assignment.

if (this == &rhs) {

return *this;

}

// Free the old memory.

delete [] mElems;

mElems = nullptr;

// Copy the new memory.

copyFrom(rhs);

return *this;

}

template

void NDGrid::resize(size_t newSize)

{

// Allocate the new array with the new size.

NDGrid* newElems = new NDGrid[newSize];

// Copy all the elements, handling the cases where newSize is

// larger than mSize and smaller than mSize.

for (size_t i = 0; i < newSize && i < mSize; i++) {

newElems[i] = mElems[i];

// Resize the nested Grid elements recursively.

newElems[i].resize(newSize);

}

// Store the new size and pointer to the new array.

// Free the memory for the old array first.

mSize = newSize;

delete [] mElems;

mElems = newElems;

}

template

NDGrid& NDGrid::operator[](size_t x)

{

return mElems[x];

}

template

const NDGrid& NDGrid::operator[](size_t x) const

{

return mElems[x];

}

Code snippet from NDGrid\NDGrid.h

Here are the implementations of the partial specialization (base case). Note that you must rewrite a lot of the code because you don’t inherit any implementations with specializations. Highlights show the differences from the non-specialized NDGrid:

template

NDGrid::NDGrid(size_t inSize) : mSize(inSize)

{

mElems = new T[mSize];

}

template

NDGrid::NDGrid(const NDGrid& src)

Return Main Page Previous Page Next Page

®Online Book Reader