// File:       deque.c++
// Version:    1.01
// Author:     (c) Miles Sabin, 1996
// Purpose:    approximation to ANSI C++ deque template

// Change log:
//  30/12/96   v. 1.00
//  11/01/97   Fiddled with inlining a bit.
//  13/01/97   Eliminated some unnecessary copying from insertion code.
//  14/01/97   v. 1.01
//             Factored out non-generic code into deque_base.
//  16/01/97   Hoist helper is now a local static to avoid static init
//               problems.
//  23/01/97   Hoist helper is now a singleton.
//  23/02/97   Adapted to HoistHelper/HoistComparator split.
//  31/03/97   Added deque(size_t) constructor.
//  04/04/97   Replaced HoistComparators with HoistBinaryPredicates.

#include "deque.h"

#include "hoistbp.h"
#include "hoistctdt.h"
#include "newcasts.h"
#include "tpltutil.h"


// Implementation of deque<T>

#define reference             T&
#define const_reference       T const&
#define iterator              T*
#define const_iterator        T const*
#define size_type             size_t
#define difference_type       ptrdiff_t
#define value_type            T
#define rev_iterator          reverse_iterator<iterator, value_type, reference>
#define const_rev_iterator    reverse_iterator<const_iterator, value_type, const_reference>

#ifndef INSTANTIATE_DEQUE_COMPARATORS_ONLY

template<class T>
deque<T>::deque()
  : deque_base(get_hoist_constructor_destructor((T*)0))
  {}

#ifndef INSTANTIATE_DEQUE_NO_DEFAULT_CTOR

template<class T>
deque<T>::deque(size_type n)
  : deque_base(get_hoist_constructor_destructor((T*)0))
  {
    T value;
    deque_base::assign(n, &value);
  }

#endif

template<class T>
deque<T>::deque(size_type n, T const& value)
  : deque_base(get_hoist_constructor_destructor((T*)0), n , &value)
  {}

template<class T>
deque<T>::deque(T const* first, T const* last)
  : deque_base(get_hoist_constructor_destructor((T*)0), first, last)
  {}

template<class T>
deque<T>::deque(deque<T> const& rhs)
  : deque_base(rhs)
  {}

template<class T>
deque<T>::~deque()
  {}

template<class T>
const_iterator deque<T>::begin() const
  { return reinterpret_cast(T const*, deque_base::begin()); }

template<class T>
const_iterator deque<T>::end() const
  { return reinterpret_cast(T const*, deque_base::end()); }

template<class T>
const_rev_iterator deque<T>::rbegin() const
  { return const_rev_iterator(end()); }

template<class T>
const_rev_iterator deque<T>::rend() const
  { return const_rev_iterator(begin()); }

template<class T>
size_type deque<T>::size() const
  { return deque_base::size(); }

template<class T>
size_type deque<T>::max_size() const
  { return deque_base::max_size(); }

template<class T>
size_type deque<T>::capacity() const
  { return deque_base::capacity(); }

template<class T>
bool deque<T>::empty() const
  { return deque_base::empty(); }

template<class T>
const_reference deque<T>::operator[](size_type n) const
  { return *reinterpret_cast(T const*, deque_base::operator[](n)); }

template<class T>
const_reference deque<T>::at(size_type n) const
  { return *reinterpret_cast(T const*, deque_base::at(n)); }

template<class T>
const_reference deque<T>::front() const
  { return *reinterpret_cast(T const*, deque_base::front()); }

template<class T>
const_reference deque<T>::back() const
  { return *reinterpret_cast(T const*, deque_base::back()); }

template<class T>
deque<T>& deque<T>::operator=(deque<T> const& rhs)
  {
    deque_base::operator=(rhs);
    return *this;
  }

template<class T>
void deque<T>::assign(T const* first, T const* last)
  { deque_base::assign(first, last); }

template<class T>
void deque<T>::assign(size_type n, T const& t)
  { deque_base::assign(n, &t); }

template<class T>
iterator deque<T>::begin()
  { return reinterpret_cast(T*, deque_base::begin()); }

template<class T>
iterator deque<T>::end()
  { return reinterpret_cast(T*, deque_base::end()); }

template<class T>
rev_iterator deque<T>::rbegin()
  { return rev_iterator(end()); }

template<class T>
rev_iterator deque<T>::rend()
  { return rev_iterator(begin()); }

template<class T>
void deque<T>::resize(size_type sz, T const& c)
  { deque_base::resize(sz, &c); }

template<class T>
reference deque<T>::operator[](size_type n)
  { return *reinterpret_cast(T*, deque_base::operator[](n)); }

template<class T>
reference deque<T>::at(size_type n)
  { return *reinterpret_cast(T*, deque_base::at(n)); }

template<class T>
reference deque<T>::front()
  { return *reinterpret_cast(T*, deque_base::front()); }

template<class T>
reference deque<T>::back()
  { return *reinterpret_cast(T*, deque_base::back()); }

template<class T>
void deque<T>::push_front(T const& x)
  { deque_base::push_front(&x); }

template<class T>
void deque<T>::pop_front()
  { deque_base::pop_front(); }

template<class T>
void deque<T>::push_back(T const& x)
  { deque_base::push_back(&x); }

template<class T>
void deque<T>::pop_back()
  { deque_base::pop_back(); }

template<class T>
iterator deque<T>::insert(iterator position, T const& x)
  { return reinterpret_cast(T*, deque_base::insert(position, &x)); }

template<class T>
void deque<T>::insert(iterator position, size_type n, T const& x)
  { deque_base::insert(position, n, &x); }

template<class T>
void deque<T>::insert(iterator position, T const* first, T const* last)
  { deque_base::insert(position, first, last); }

template<class T>
void deque<T>::erase(iterator position)
  { deque_base::erase(position); }

template<class T>
void deque<T>::erase(iterator first, iterator last)
  { deque_base::erase(first, last); }

template<class T>
void deque<T>::swap(deque<T>& x)
  { deque_base::swap(x); }

template<class T>
void deque<T>::clear()
  { deque_base::clear(); }

#endif

#undef reference
#undef const_reference
#undef iterator
#undef const_iterator
#undef size_type
#undef difference_type
#undef value_type
#undef rev_iterator
#undef const_rev_iterator


// Implementation of deque<T> free fns

#ifndef INSTANTIATE_DEQUE_NON_COMPARATORS_ONLY

template<class T>
bool operator==(deque<T> const& lhs, deque<T> const& rhs)
{
  return REF_reinterpret_cast(deque_base, lhs).is_equal(get_hoist_equal_to_comparator((T*)0), REF_reinterpret_cast(deque_base, rhs));
}

template<class T>
bool operator< (deque<T> const& lhs, deque<T> const& rhs)
{
  return REF_reinterpret_cast(deque_base, lhs).is_less_than(get_hoist_less_comparator((T*)0), REF_reinterpret_cast(deque_base, rhs));
}

#endif
