Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |
You can easily derive from a class template, and you can
create a new template that instantiates and inherits from an existing template.
If the vector template does most everything you want, for example, but in
a certain application you d also like a version that can sort itself, you can
easily reuse the vector code. The following example derives from vector<T>
and adds sorting. Note that deriving from vector, which doesn t have a
virtual destructor, would be dangerous if we needed to perform cleanup in our
destructor.
//: C05:Sortable.h
// Template specialization.
#ifndef SORTABLE_H
#define SORTABLE_H
#include <cstring>
#include <cstddef>
#include <string>
#include <vector>
using std::size_t;
template<class T>
class Sortable : public std::vector<T> {
public:
void sort();
};
template<class T>
void Sortable<T>::sort() { // A simple sort
for(size_t i = this->size(); i > 0; --i)
for(size_t j = 1; j < i; ++j)
if(this->at(j-1) > this->at(j)) {
T t = this->at(j-1);
this->at(j-1) = this->at(j);
this->at(j) = t;
}
}
// Partial specialization for
pointers:
template<class T>
class Sortable<T*> :
public std::vector<T*> {
public:
void sort();
};
template<class T>
void Sortable<T*>::sort() {
for(size_t i = this->size(); i > 0; --i)
for(size_t j = 1; j < i; ++j)
if(*this->at(j-1) > *this->at(j)) {
T* t = this->at(j-1);
this->at(j-1) = this->at(j);
this->at(j) = t;
}
}
// Full specialization for char*
// (Made inline here for
convenience -- normally you would
// place the function body in a separate
file and only
// leave the declaration here).
template<> inline void Sortable<char*>::sort()
{
for(size_t i = this->size(); i > 0; --i)
for(size_t j = 1; j < i; ++j)
if(std::strcmp(this->at(j-1), this->at(j))
> 0) {
char* t = this->at(j-1);
this->at(j-1) = this->at(j);
this->at(j) = t;
}
}
#endif // SORTABLE_H ///:~
The Sortable template imposes a restriction on all
but one of the classes for which it is instantiated: they must contain a >
operator. It works correctly only with non-pointer objects (including objects
of built-in types). The full specialization compares the elements using strcmp( )
to sort vectors of char* according to the null-terminated strings
to which they refer. The use of this-> above is mandatory and is
explained in the section entitled Name lookup issues later in this chapter.
Here s a driver for Sortable.h that uses the randomizer
introduced earlier in the chapter:
//: C05:Sortable.cpp
//{-bor} (Because of bitset in Urand.h)
// Testing template specialization.
#include <cstddef>
#include <iostream>
#include "Sortable.h"
#include "Urand.h"
using namespace std;
#define asz(a) (sizeof a / sizeof a[0])
char* words[] = { "is", "running",
"big", "dog", "a", };
char* words2[] = { "this", "that",
"theother", };
int main() {
Sortable<int> is;
Urand<47> rnd;
for(size_t i = 0; i < 15; ++i)
is.push_back(rnd());
for(size_t i = 0; i < is.size(); ++i)
cout << is[i] << ' ';
cout << endl;
is.sort();
for(size_t i = 0; i < is.size(); ++i)
cout << is[i] << ' ';
cout << endl;
// Uses the template partial specialization:
Sortable<string*> ss;
for(size_t i = 0; i < asz(words); ++i)
ss.push_back(new string(words[i]));
for(size_t i = 0; i < ss.size(); ++i)
cout << *ss[i] << ' ';
cout << endl;
ss.sort();
for(size_t i = 0; i < ss.size(); ++i) {
cout << *ss[i] << ' ';
delete ss[i];
}
cout << endl;
// Uses the full char* specialization:
Sortable<char*> scp;
for(size_t i = 0; i < asz(words2); ++i)
scp.push_back(words2[i]);
for(size_t i = 0; i < scp.size(); ++i)
cout << scp[i] << ' ';
cout << endl;
scp.sort();
for(size_t i = 0; i < scp.size(); ++i)
cout << scp[i] << ' ';
cout << endl;
} ///:~
Each of the template instantiations above uses a different
version of the template. Sortable<int> uses the primary template. Sortable<string*>
uses the partial specialization for pointers. Last, Sortable<char*>
uses the full specialization for char*. Without this full
specialization, you could be fooled into thinking that things were working
correctly because the words array would still sort out to a big dog is
running since the partial specialization would end up comparing the first
character of each array. However, words2 would not sort correctly.
Thinking in C++ Vol 2 - Practical Programming |
Prev |
Home |
Next |