friend in nested member template (in level 2)
 
I was practicing some simple questions, and tried to create a queue in
terms of a stack (using templates). The question if simple, but I am
making a silly mistake while printing the stack. I DON'T WANT TO USE
CONTAINMENT USING TEMPLATE PARAMETERS.
The problem lays in how to print queue in terms of a stack. I get the
following error using Visual Studio 2005 (C++):
"qfrmstk.h(123) : error C2679: binary '<<' : no operator found which
takes a right-hand operand of type 'Queue<>::Stack<S>' (or there is no
acceptable conversion)"
Here is the code:-
----------------------------------------------------------
//Program to create a Queue from stack
#ifndef   QFRMSTK_H
#define   QFRMSTK_H
#include <iostream>
#include <exception>
struct Underflow: public std::exception {
    Underflow():std::exception("Queue Undeflow."){}
};
template<typename Q=int> class Queue{
    template<typename S=int> class Stack{
        template<typename N=int> struct Node{
            Node *next;
            N info;
            Node():next(0){}
            Node(N inf):next(0), info(inf){}
            Node(N inf, Node* nxt):next(nxt), info(inf){}
        };
        Node<S> *top;
    public:
        Stack():top(0){}
        ~Stack();
        S Pop();
        void Push(S info);
        bool isEmpty() const;
        template<typename U> friend std::ostream& operator <<
(std::ostream&, Stack<U>&);
        //HACK: (for above operation to work)
        std::ostream& ShowContents(std::ostream& strm){
            if(!this->top) return strm;
            typename Node<S> *current= this->top;
            while(current){
                strm << current->info<<' ';
                current = current->next;
            }
            return strm;
        }
    };
    Stack<Q> pool;
    int elements;
public:
    Queue():pool(),elements(0){}
    //~Queue(); //not needed as pool is not a pointer
    void Enqueue(Q info);
    Q Dequeue();
    bool isEmpty() const;
    template<typename U> friend std::ostream& operator << (std::ostream&,
Queue<U>&);
};
template<typename Q> template<typename S> Queue<Q>::Stack<S>::~Stack()
{
    if(!this->top) return;
    typename Queue<Q>::Stack<S>::Node<S> *current = this->top;
    typename Queue<Q>::Stack<S>::Node<S> *rem;
    while(current){
        rem = current;
        current = current->next;
        delete rem;
    }
    this->top = 0;
}
template<typename Q> template<typename S> S Queue<Q>::Stack<S>::Pop(){
    if(!this->top) throw Underflow();
    typename Queue<Q>::Stack<S>::Node<S> *rem = this->top;
    Q ret = rem->info;
    this->top = this->top->next;
    delete rem;
    return ret;
}
template<typename Q> template<typename S> void
Queue<Q>::Stack<S>::Push(S info){
    try{
        if(!this->top)
            this->top = new typename Queue<Q>::Stack<S>::Node<S> (info);
        else
            this->top = new typename Queue<Q>::Stack<S>::Node<S>(info, this-
top);
    
}
    catch(std::bad_alloc){
        std::cerr<<" out of memory.";
    }
}
template<typename Q> template<typename S> bool
Queue<Q>::Stack<S>::isEmpty() const{
    return !this->top;
}
//  SEE THE HACK ABOVE
template<typename U> std::ostream& operator << (std::ostream& strm,
                                                            typename Queue<U>::Stack<U>& s){
    if(!s.top) return strm;
    typename Queue<U>::Stack<U>::Node<U> *current;
    while(current){
        strm << current->info;
        current = current->next;
    }
    return strm;
}
//*/
template<typename Q> void Queue<Q>::Enqueue(Q info){
    typename Queue<Q>::Stack<Q> temp;
    while(!pool.isEmpty())
        temp.Push(pool.Pop());
    pool.Push(info);
    while(!temp.isEmpty())
        pool.Push(temp.Pop());
}
template<typename Q> Q Queue<Q>::Dequeue(){
    return pool.Pop ();
}
template<typename Q> bool Queue<Q>::isEmpty()const{
    return pool.isEmpty();
}
//////// ERROR HERE:-
template<typename U> std::ostream& operator << (std::ostream& strm,
Queue<U>& q){
    //return q.pool.ShowContents(strm);
    strm << q.pool;
    return strm;
}
int test(){
    Queue<> q;
    q.Enqueue (1);
    q.Enqueue (2);
    q.Enqueue (3);
    q.Enqueue (4);
    std::cout<<q;
    return 0;
}
#endif // QFRMSTK_H
Regards,
Zaman