`

c++ template class and the pattern to use its friends

    博客分类:
  • c++
c++ 
阅读更多

template class may defined their friends template function, friend function or even friend class to aid it provide some functions. 

 

But normally how do you implements the with the friends?

 

Let's see the following examples on the Queue and the QueueItem classes 

 

 

 

#include <iostream>
#include <string>
using std::istream;
using std::ostream;

template <class Type>
class QueueItem;

template <class Type>
void foo(QueueItem<Type>);

template <class Type>
class Queue 
{
public:
	friend void foo(Queue<Type>); // - this mean foo is a non-template function, it is just a normal function which accepts the parameter of type Queue<Type>
	// or you can write as follow
	friend void foo<Type>(Queue<Type>); // - this means that foo is a template function

	// whether we should write as 
	template<class Type>       // since we cannot do as friend ostream& operator << (ostream&, const Queue<Type> &);, we have to provide the templtae<class Type> is there better ways?
	friend ostream& operator <<(ostream& , const Queue<Type> &);
	// or as 
	//friend operator <<(ostream&, const Queue<Type> &);
	// while you cannoot provide type parameter as the non-operator normal function template 
	//friend ostream& operator << <Type>(ostream&, const Queue<Type> &);
	// this is a partial function instantiation
	//template <> friend ostream& operator << (ostream& , const Queue<Type> &);
protected:
	virtual ostream& print(ostream&) const;
private:
	QueueItem<Type> *front;
	QueueItem<Type> *back;
};

template <class Type>
class QueueItem
{
public:
	// all queue instantiation are friends
	// to each QueueItem instantiation
	//template <class T> friend class Queue; // it is not "friend template <class T> class Queue;
	friend class Queue<Type>;
	//
	//friend ostream& operator << <Type>(ostream &, const Queue<Type> &);
	// or you can write as follow
	template<class Type>
	friend ostream& operator << (ostream &, const QueueItem<Type> &);
	template<class Type>
	friend ostream& operator << (ostream &, const Queue<Type> &);
	//template <class T> friend ostream& operator << (ostream& , const QueueItem<T> &);
	operator Type () { return value; } // - the data accessor 
protected:
	virtual ostream& print(ostream &) const;
private:
	QueueItem<Type> *next;
	Type            value;
};

// and if you want to define the helper ostream oeprator, how would you do that 
// you can make the function a template function
//
template <class Type>
ostream& operator <<(ostream &, const Queue<Type> &);

// and how is it implemented
template <class Type>
ostream& operator <<(ostream &os, const Queue<Type> & q)
{
	os << "< ";
	QueueItem<Type>* p;
	for (p = q.front; p; p = p->next) { 
		os << *p << " ";
	}
	os << "> ";
	return os;
}

template <class Type>
ostream& operator <<(ostream& os, const QueueItem<Type> & q)
{
	os << q.value;
	return os;
}

 

 

  1. the code we have examine the 
  2. friend template function 
  3. friend function 
  4. and friend classes 

 

we also have examined the difference of writting 

 

 

 

friend void foo<Type>(Queue<Type>);
 

 

 

and 

 

 

friend void foo(Queue<Type>);
 

 

 

and we will see that why we need to write 

 

 

template <class Type>
friend ostream& operator <<(ostream& , Queue<Type>);
 

 

 

 

rather than 

 

 

template <class Type>
friend ostream& operator <<(ostream& , Queue<Type>);
 

 

 

But is that all, is that all we can do ?

 

what if there is derived class to Queue<T> or QueueItem<T> , here is the improved code

 

do you see the code , where we have defined the virtual print method.

 

 

virtual ostream& print(ostream&) const;

 

 

and no

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics