c++ - template specialization and partial specialization

in this post, we are going to examining partialization.

 

There are two kind of partialization, one is full specialization, and the other is partial specialization.

 

  • full specialization
  • partial specialization

 

 

 

Full specialization

 

 

class

 

  •      QueueItem
  •      Queue

 

Are used for full specialization, by full specialization, it means once specialized, there exist only one instance for the specialized template arguments.

 

 

see the code below. 

 

 

/**
* file
*  template_specialization.h
* description:
*   template specialization and partial specialization
*/


#include <iostream>
#include <string>
#include <assert.h>
#include <cassert>

using std::string;
using std::ostream;
using std::istream;
using std::cerr;
using std::cout;
using std::endl;
using std::exit;

/**
*
*  class
*     QueueItem
*     Queue
*  are used for full specialization, by full specialization, it means once specialized, there exist only one instance for the specialized template arguments.
* 
* Later we will discuss  parital specialization
*/

template<class Type>
class QueueItem
{
public:
	QueueItem(const Type &val) : next(0), value (val)  {} 

	QueueItem<Type> *next;
	Type value;
protected:
};


template <class Type>
class Queue 
{
public:
	Queue() : front(0), back (0) {} 
	~Queue() ;
	Type remove();
	Type min();
	Type max();

	void add(const Type &);
	bool is_empty() const {
		return front == 0;
	}

	// class member template
	// with this you can define 
	// things like Queue<int>::CL<string> ...
	// which may sound useless at the frist glance, but we will see
	template <class T>
	class CL
	{
		T name;
		Type mem;
	};

	template <class Iter>
	void assign(Iter first, Iter last)
	{
		while (!is_empty()) 
			remove(); // call Queue<T>::remove
		for (; first != last; ++first) 
			add(*first);
	}

private:
	QueueItem<Type> *front;
	QueueItem<Type> *back;
protected:
};

class LongDouble 
{
public:
	LongDouble(double dval) : value(dval) {}
	bool compareLess(const LongDouble & rhs) { return value < rhs.value;  }
private:
	double value;
protected:
};

template <class Type>
Queue<Type>::~Queue()
{
	while (!is_empty()) {
		remove();
	}
}

template <class Type>
void Queue<Type>::add(const Type &val)
{

	QueueItem<Type> *pt = new QueueItem<Type>(val);
	if (is_empty())
	{
		front = back = pt;
	}
	else 
	{
		back->next = pt;
	}
	
}


template <class Type>
Type Queue<Type>::remove()
{
	if (is_empty()) {
		cerr << "remove() on empty queue\n";
		exit(-1);
	}
	QueueItem<Type> *pt = front;
	front = front->next;
	Type retval =  pt->value;
	delete pt;
	return retval;
}


// find minimum value in the queue
template <class Type>
Type Queue<Type>::min()
{
	assert(! is_empty());
	Type min_value = front->value;
	for (QueueItem<Type> * pq = front->next; pq != 0; pq = pq->next)
	{
		if (pq->value < min_val)
			min_val = pq->value;
	}
	return min_val;
}

template <class Type>
Type Queue<Type>::max()
{
	assert(! is_empty());
	Type max_val = front->value;
	for (QueueItem<Type> * pq = front->next; pq != 0; pq = pq->next)
	{
		if (pq->value > max_val);
			max_val = pq->value;
	}
	return max_val;
}


/**
* template<>
*   LongDouble Queue<LongDouble>::min()
* 
* this is the specialization of member
* which once is defind, will create a specialization on the class of template<> class Queue<LongDouble>;
* 
* also, if the specialization will totally redefine the data members, not just the member functions, you can try the 
* full specialization on class as well.
*  
*  template<>
*  class <void *> Queue{ };
*
* you cannot do 
*   specialization member 
*   specialization on the class
* at the same time
*
* this is full specialization, while you can do partial specialization, please refer the partial specialization later on this chapter
*/
template <>
LongDouble Queue<LongDouble>::min() 
{
	assert(! is_empty());
	LongDouble min_val = front->value;
	for (QueueItem<LongDouble> * pq = front->next; pq != 0; pq = pq->next)
	{
		if (pq->value.compareLess(min_val))
			min_val = pq->value;
	}
	return min_val;
}


/**
* template<>
*   LongDouble Queue<LongDouble>::min()
* 
*/
template <>
LongDouble Queue<LongDouble>::max()
{
	assert(! is_empty());
	LongDouble max_val = front->value;
	for (QueueItem<LongDouble> * pq = front->next; pq != 0; pq = pq->next)
	{
		if (!pq->value.compareLess(max_val))
			max_val = pq->value;
	}
	return max_val;
}

 

 

As we have described in the code above, you can do template specialization on the data member, you can also do specialization on the the template class itself. as below.

 

 

template<>
class Queue<void *>
{
public:
	Queue() : front(0), back (0) {} 
	~Queue() ;
	void* remove();
	void* min();
	void* max();

private:
	QueueItem<void *> *front;
	QueueItem<void *> *back;
protected:

};
 

 

while, let me restate/reiterate/rephraze/recapitulate the that 

you cannot do 

 

  1. specialization on member function 
  2. specialization on class template

 

at the same time. 

 

partial specialization

unlike the full specialization, which will have only one template instance for the particular specialized type parameter. while, partial specialization results in another template, which has infinite set of instances.

 

let's see an example. 

 

 

/**
*
*  class
*     Screen
*  are used for partial specialization, by partial which means after the specialization, there still exist inifinite set of template instances based on the unspecialized type parameter.
*/

template<int hi, int wid>
class Screen
{
	//...
};

/**
* fixed (specialized) the wid non-type template parameter to 80, if the template class has type template parameter, we can fixed the 
*/
template<int hi>
class Screen<hi, 80>
{
public:
	Screen();
private:
	string _screen;
	string::size_type _cursor;
	short _height;
//	 use the special 
};

/**
* template<int hi>
* Screen<hi, 80>::Screen()
*
*/
template<int hi>
Screen<hi, 80>::Screen() : _screen(""), _cursor(string("").size), _height(80)
{
}
 

 

 

while the above code shows partial specialization on the type parameters. let's seen the example. 

 

 

/*
* template<class T1, class T2>
* class Foo {}
* 
* shows how to do partial specialization on type parameter template class.
*/
template<class T1, class T2>
class Foo
{
};

template<class T1>
class Foo<T1, string>
{
};
 

 

 

 

你可能感兴趣的:(C++)