#include <ostream>

namespace std
{
   template <class T, class A> class vector;
   template <class T, class A>
   ostream & operator << (ostream & o, const vector<T,A> & vec)
   {
      int n = vec.size();
      o << "[vector (" << n << " element" << (n==1 ? "):" : "s):");
      for (int i = 0; i < n; ++i)
	 o << (i==0 ? " " : ",") << "[" << i << "] " << vec[i];
      return o << "]";
   }

   template <class T, class A> class list;
   template <class T, class A>
   ostream & operator << (ostream & o, const list<T,A> & l)
   {
      int n = l.size();
      o << "[list (" << n << " element" << (n==1 ? "):" : "s):");
      for (typename list<T,A>::const_iterator it = l.begin(); it != l.end(); ++it)
	 o << (it==l.begin() ? " " : ",") << *it;
      return o << "]";
   }

   template <class T, class A> class deque;
   template <class T, class A>
   ostream & operator << (ostream & o, const deque<T,A> & dq)
   {
      int n = dq.size();
      o << "[deque (" << n << " element" << (n==1 ? "):" : "s):");
      for (int i = 0; i < n; ++i)
	 o << (i==0 ? " " : ",") << "[" << i << "] " << dq[i];
      return o << "]";
   }

   template <class T, class C> class stack;
   template <class T, class C>
   ostream & operator << (ostream & o, const stack<T,C> & st)
   {
      int n = st.size();
      return o << "[stack (" << n << " element" << (n==1 ? " " : "s ") << "-- top element: " << st.top() << "]";
   }

   template <class T, class C> class queue;
   template <class T, class C>
   ostream & operator << (ostream & o, const queue<T,C> & q)
   {
      int n = q.size();
      return o << "[queue (" << n << " element" << (n==1 ? " " : "s ") << "-- last in: " << q.back() << " -- next out: " << q.front() << "]";
   }

   template <class T, class C, class Cmp> class priority_queue;
   template <class T, class C, class Cmp>
   ostream & operator << (ostream & o, const priority_queue<T,C,Cmp> & pq)
   {
      int n = pq.size();
      return o << "[priority_queue (" << n << " element" << (n==1 ? " " : "s ") << "-- highest priority: " << pq.top() << "]";
   }

   template <class Key, class T, class Cmp, class A> class map;
   template <class Key, class T, class Cmp, class A>
   ostream & operator << (ostream & o, const map<Key,T,Cmp,A> & mp)
   {
      int n = mp.size();
      o << "[map (" << n << " element" << (n==1 ? "):" : "s):");
      for (typename map<Key,T,Cmp,A>::const_iterator it = mp.begin(); it != mp.end(); ++it)
	 o << (it==mp.begin() ? " " : ",") << "[" << it->first << "] " << it->second;
      return o << "]";
   }

   template <class Key, class T, class Cmp, class A> class multimap;
   template <class Key, class T, class Cmp, class A>
   ostream & operator << (ostream & o, const multimap<Key,T,Cmp,A> & mmp)
   {
      int n = mmp.size();
      o << "[multimap (" << n << " element" << (n==1 ? "):" : "s):");
      for (typename multimap<Key,T,Cmp,A>::const_iterator it = mmp.begin(); it != mmp.end(); ++it)
	 o << (it==mmp.begin() ? " " : ",") << "[" << it->first << "] " << it->second;
      return o << "]";
   }

   template <class Key, class Cmp, class A> class set;
   template <class Key, class Cmp, class A>
   ostream & operator << (ostream & o, const set<Key,Cmp,A> & s)
   {
      int n = s.size();
      o << "[set (" << n << " element" << (n==1 ? "):" : "s):");
      for (typename set<Key,Cmp,A>::const_iterator it = s.begin(); it != s.end(); ++it)
	 o << (it==s.begin() ? " " : ",") << *it;
      return o << "]";
   }
 
   template <class Key, class Cmp, class A> class multiset;
   template <class Key, class Cmp, class A>
   ostream & operator << (ostream & o, const multiset<Key,Cmp,A> & ms)
   {
      int n = ms.size();
      o << "[multiset (" << n << " element" << (n==1 ? "):" : "s):");
      for (typename multiset<Key,Cmp,A>::const_iterator it = ms.begin(); it != ms.end(); ++it)
	 o << (it==ms.begin() ? " " : ",") << *it;
      return o << "]";
   }
}

