Professional C__ - Marc Gregoire [352]
The compiler always chooses the “most specific” version of the function, with non-template versions being preferred over template versions.
The following code calls the specified versions of Find():
size_t res = NOT_FOUND;
int x = 3, intArr[] = {1, 2, 3, 4};
size_t sizeArr = sizeof(intArr) / sizeof(int);
res = Find(x, intArr, sizeArr); // calls Find res = Find double d1 = 5.6, dArr[] = {1.2, 3.4, 5.7, 7.5}; sizeArr = sizeof(dArr) / sizeof(double); res = Find(d1, dArr, sizeArr); // calls Find res = Find char* word = "two"; char* arr[] = {"one", "two", "three", "four"}; sizeArr = sizeof(arr) / sizeof(arr[0]); res = Find res = Find(word, arr, sizeArr); // calls overloaded Find for char*s int *px = &x, *pArr[] = {&x, &x}; sizeArr = sizeof(pArr) / sizeof(pArr[0]); res = Find(px, pArr, sizeArr); // calls the overloaded Find for pointers SpreadsheetCell c1(10), c2[] = {SpreadsheetCell(4), SpreadsheetCell(10)}; sizeArr = sizeof(c2) / sizeof(c2[0]); res = Find(c1, c2, sizeArr); // calls Find // calls Find res = Find SpreadsheetCell *pc1 = &c1; SpreadsheetCell *psa[] = {&c1, &c1}; sizeArr = sizeof(psa) / sizeof(psa[0]); res = Find(pc1, psa, sizeArr); // Calls the overloaded Find for pointers Code snippet from FunctionTemplatePtr\FindTemplatePtr.cpp TEMPLATE RECURSION This section employs some operator overloading features which are discussed in Chapter 18. If you skipped that chapter or are unfamiliar with the syntax for overloading operator[], consult Chapter 18 before continuing. An N-Dimensional Grid: First Attempt The Grid template example up to now supports only two dimensions, which limits its usefulness. What if you wanted to write a 3-D Tic-Tac-Toe game or write a math program with four-dimensional matrices? You could, of course, write a template or non-template class for each of those dimensions. However, that would repeat a lot of code. Another approach is to write only a single-dimensional grid. Then, you could create a Grid of any dimension by instantiating the Grid with another Grid as its element type. This Grid element type could itself be instantiated with a Grid as its element type, and so on. Here is the implementation of the OneDGrid class template. It’s simply a one-dimensional version of the Grid template from the earlier examples, with the addition of a resize() method, and the substitution of operator[] for setElementAt() and getElementAt(). Production code, of course, would do bounds-checking on the array access, and would throw an exception if something were amiss. template class OneDGrid { public: OneDGrid(size_t inSize = kDefaultSize); OneDGrid(const OneDGrid virtual ~OneDGrid(); OneDGrid 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 OneDGrid T* mElems; size_t mSize; }; template OneDGrid { mElems = new T[mSize]; } template OneDGrid { copyFrom(src); }
Templates in C++ provide capabilities that go far beyond the simple classes and functions you have seen so far in this and the previous chapter. One of these capabilities is template recursion. This section first provides a motivation for template recursion, and then shows how to implement it.