模板4(template)

1、Making a Function Template a Friend

The output operator needs to be a friend of both the Queue and QueueItem classes. It uses the head member of class Queue and the next and item members of class QueueItem . Our classes grant friendship to the specific instance of the output operator instantiated with the same type:

// function template declaration must precede friend declaration in QueueItem
template <class T>
std::ostream& operator<<(std::ostream&, const Queue<T>&);
template <class Type> class QueueItem {
friend class Queue<Type>;
// needs access to item and next
friend std::ostream&
operator<< <Type> (std::ostream&, const Queue<Type>&);
// ...
};
template <class Type> class Queue {
// needs access to head
friend std::ostream&
operator<< <Type> (std::ostream&, const Queue<Type>&);
};

Each friend declaration grants access to the corresponding instantiation of the operator<< . That is, the output operator that prints a Queue<int> is a friend to class Queue<int> (and QueueItem<int>) . It is not a friend to any other Queue type.

2、Type Dependencies and the Output Operator

The Queue output operator<< relies on the operator<< of item to actually print each element:  os << p->item << " ";

When we use p->item as an operand of the << operator, we are using the << defined for whatever type item has  This code is an example of a type dependency between Queue and the element type that Queue holds. In effect, each type bound to Queue that uses the Queue output operator must itself have an output operator. There is no language mechanism to specify or enforce that dependency in the definition of Queue itself. It is legal to create a Queue for a class that does not define the output operator but it is a compile-time (or link-time) error to print a Queue holding such a type.

3、Defining a Member Template

template <class Type> class Queue {
public:
// construct a Queue from a pair of iterators on some sequence
template <class It>
Queue(It beg, It end):
head(0), tail(0) { copy_elems(beg, end); }
// replace current Queue by contents delimited by a pair of iterators
template <class Iter> void assign(Iter, Iter);
// rest of Queue class as before
private:
// version of copy to be used by assign to copy elements from iterator range
template <class Iter> void copy_elems(Iter, Iter);
};

The member declaration starts with its own template parameter list. The constructor and assign member each have a single template type parameter. These functions use that type parameter as the type for their function parameters, which are iterators denoting a range of elements to copy.

4、Defining a Member Template Outside the Class

When we define a member template outside the scope of a class template, we must include both template parameter lists:

template <class T> template <class Iter>
void Queue<T>::assign(Iter beg, Iter end)
{
destroy(); // remove existing elements in this Queue
copy_elems(beg, end); // copy elements from the input range
}

When a member template is a member of a class template, then its definition must include the class-template parameters as well as its own template parameters. The class-template parameter list comes first, followed by the member's own template parameter list.

posted on 2014-05-30 11:13  江在路上2  阅读(94)  评论(0)    收藏  举报