/** @file

    $Id$

    $Date$
    $Author$

    @copy &copy; Marc W&auml;ckerlin
    @license LGPL, see file <a href="license.html">COPYING</a>

    $Log$
    Revision 1.4  2005/11/29 12:39:42  marc
    make it compilable with gcc 4.0.2 and newer doxygen

    Revision 1.3  2005/04/07 20:48:20  marc
    docu: new doxygen, new grouping

    Revision 1.2  2004/12/20 07:40:35  marc
    documentation improved, new grouping

    Revision 1.1  2004/10/07 09:31:30  marc
    new feature


*/
#ifndef __MRW__DEQUE__HPP__
#define __MRW__DEQUE__HPP__

#include <deque>
#include <mrw/checkcxx11.hxx>
#include <mrw/exception.hxx>
#include <mrw/string.hxx>

/** @addtogroup StdExtSTL
 */
//@{
/** @defgroup StdExtdeque deque
 */
//@{

/** @brief push a value to a deque

    @code
    std::deque<int> test;
    test<<1<<2<<3<<4<<5<<6<<7<<8;
    @endcode

    @param l a deque of values
    @param o a value to be inserted into deque @c l
    @pre \#include <mrw/deque.hxx>
*/
template <typename T, typename A>
    std::deque<T, A>& operator<<(std::deque<T, A>& l, const T& o)
    throw(std::bad_exception) {
  l.push_back(o);
  return l;
}

/** @brief push a value to a constant deque

    Makes a copy and returns the copy.

    @code
    std::deque<int>()<<1<<2<<3<<4<<5<<6<<7<<8;
    @endcode

    @param l a deque of values
    @param o a value to be inserted into deque @c l
    @pre \#include <mrw/deque.hxx>
*/
template <typename T, typename A>
    std::deque<T, A> operator<<(const std::deque<T, A>& l, const T& o)
    throw(std::bad_exception) {
  std::deque<T, A> copy(l);
  copy.push_back(o);
  return copy;
}

/* @brief push a char* to a dequeue of string

    @code
    std::dequeue<std::string> test;
    test<<"Hello"<<"World";
    @endcode

    @param l a dequeue of string values (that can be constructed from char*)
    @param o a value to be inserted into dequeue @c l
    @pre \#include <mrw/dequeue.hxx> */
template <typename T, typename A>
    std::deque<T, A>& operator<<(std::deque<T, A>& l,
                               const char *const o)
    throw(std::bad_exception) {
  l.push_back(T(o));
  return l;
}

/** @brief extract the first value of a deque

    @code
    std::deque<int> test;
    test<<1<<2<<3<<4<<5<<6<<7<<8;
    int i1(0), i2(0), i3(0), i4(0);
    test>>i1>>i2>>i3>>i4;
    // now: i1==1 i2==2 i3==3 i4==4 test=={5, 6, 7, 8}
    @endcode

    @param l a deque of values
    @param o a value to be extracted from deque @c l
    @throw mrw::length_error, if deque was empty on entry
    @note when something is extracted from a deque, it is removed
    from the deque, that means after every shift the deque is
    shortened by the shifted element
    @pre \#include <mrw/deque.hxx>
*/
template <typename T, typename A>
    std::deque<T, A>& operator>>(std::deque<T, A>& l, T& o)
    throw(std::exception) {
  typename std::deque<T, A>::iterator it(l.begin());
  if (it==l.end())
    throw mrw::length_error(std::string(__FILE__ ":")+__LINE__+
                            ": std::deque<>& operator>>(std::deque<>&, T&),"
                            " deque is empty");
  o = *it;
  l.erase(it);
  return l;
}

//@}
//@}

#endif
