模板的特殊化

一个特殊化的例子

//: C03:Sorted.h

// Template specialization

#ifndef SORTED_H

#define SORTED_H

#include <vector>

template<class T>

class Sorted : public std::vector<T>

{

public:

void sort();

};

template<class T>

void Sorted<T>::sort()

{

// A bubble sort

for(int i = size(); i > 0; i--)

for(int j = 1; j < i; j++)

if(at(j-1) > at(j))

{

// Swap the two elements:

T t = at(j-1);

at(j-1) = at(j);

at(j) = t;

}

}

// Partial specialization for pointers:

template<class T>

class Sorted<T*> : public std::vector<T*>

{

public:

void sort();

};

template<class T>

void Sorted<T*>::sort()

{

for(int i = size(); i > 0; i--)

for(int j = 1; j < i; j++)

if(*at(j-1) > *at(j))

{

// Swap the two elements:

T* t = at(j-1);

at(j-1) = at(j);

at(j) = t;

}

}

// Full specialization for char*:

template<>

void Sorted<char*>::sort()

{

for(int i = size(); i > 0; i--)

for(int j = 1; j < i; j++)

if(strcmp(at(j-1), at(j)) > 0)

{

// Swap the two elements:

char* t = at(j-1);

at(j-1) = at(j);

at(j) = t;

}

}

#endif // SORTED_H ///:~

//: C03:Sorted.cpp

// Testing template specialization

#include "Sorted.h"

#include "Urand.h"

#include "../arraySize.h"

#include <iostream>

#include <string>

using namespace std;

char* words[] = {

"is", "running", "big", "dog", "a",

};

char* words2[] = {

"this", "that", "theother",

};

int main()

{

Sorted<int> is;

Urand<47> rand;

for(int i = 0; i < 15; i++)

is.push_back(rand());

for(int l = 0; l < is.size(); l++)

cout << is[l] << ' ';

cout << endl;

is.sort();

for(int l = 0; l < is.size(); l++)

cout << is[l] << ' ';

cout << endl;

// Uses the template partial specialization:

Sorted<string*> ss;

for(int i = 0; i < asz(words); i++)

ss.push_back(new string(words[i]));

for(int i = 0; i < ss.size(); i++)

cout << *ss[i] << ' ';

cout << endl;

ss.sort();

for(int i = 0; i < ss.size(); i++)

cout << *ss[i] << ' ';

cout << endl;

// Uses the full char* specialization:

Sorted<char*> scp;

for(int i = 0; i < asz(words2); i++)

scp.push_back(words2[i]);

for(int i = 0; i < scp.size(); i++)

cout << scp[i] << ' ';

cout << endl;

scp.sort();

for(int i = 0; i < scp.size(); i++)

cout << scp[i] << ' ';

cout << endl;

} ///:~

设计和效率

1．  得到正确的类的接口。

2．  尽可能精确的实现，当然也要尽可能的快。

3．  验证你的设计

防止模板膨胀

//: C03:Nobloat.h

// Templatized InheritStack.cpp

#ifndef NOBLOAT_H

#define NOBLOAT_H

#include "../C0A/Stack4.h"

template<class T>

class NBStack : public Stack

{

public:

void push(T* str)

{

Stack::push(str);

}

T* peek() const

{

return (T*)Stack::peek();

}

T* pop()

{

return (T*)Stack::pop();

}

~NBStack();

};

// Defaults to heap objects & ownership:

template<class T>

NBStack<T>::~NBStack()

{

T* top = pop();

while(top)

{

delete top;

top = pop();

}

}

#endif // NOBLOAT_H ///:~

//: C03:NobloatTest.cpp

#include "Nobloat.h"

#include "../require.h"

#include <fstream>

#include <iostream>

#include <string>

using namespace std;

int main(int argc, char* argv[])

{

requireArgs(argc, 1); // File name is argument

ifstream in(argv[1]);

assure(in, argv[1]);

NBStack<string> textlines;

string line;

// Read file and store lines in the stack:

while(getline(in, line))

textlines.push(new string(line));

// Pop the lines from the stack and print them:

string* s;

while((s = (string*)textlines.pop()) != 0)

{

cout << *s << endl;

delete s;

}

} ///:~

外部实例化

template void sort<char>(char*[]);

//: C03:ExplicitInstantiation.cpp

#include "Urand.h"

#include "Sorted.h"

#include <iostream>

using namespace std;

// Explicit instantiation:

template class Sorted<int>;

int main()

{

Sorted<int> is;

Urand<47> rand1;

for(int k = 0; k < 15; k++)

is.push_back(rand1());

is.sort();

for(int l = 0; l < is.size(); l++)

cout << is[l] << endl;

} ///:~

控制模板实例化

//: C03:DelayedInstantiation.cpp

// Member functions of class templates are not

// instantiated until they're needed.

class X

{

public:

void f() {}

};

class Y

{

public:

void g() {}

};

template <typename T> class Z

{

T t;

public:

void a() { t.f(); }

void b() { t.g(); }

};

int main()

{

Z<X> zx;

zx.a(); // Doesn't create Z<X>::b()

Z<Y> zy;

zy.b(); // Doesn't create Z<Y>::a()

} ///:~

0 0