#ifndef _MAPITL_CELL_TMPL_H
#define _MAPITL_CELL_TMPL_H

#include<stdexcept>
#include<string>
#include "MAPITL.h"

template<class S, class T>
MAPITL::Cell::Cell(std::pair<S,T> p) {
  cell = MFnewList(2);
  MFsetList(&cell, 0, MTcell(Cell(p.first)));
  MFsetList(&cell, 1, MTcell(Cell(p.second)));
  sign();
}

//////////////////////////////////////////////////////////////////////////////
// Container class
//////////////////////////////////////////////////////////////////////////////

bool
MAPITL::Cell::empty    () const { return MFnopsList(cell)==0; }

MAPITL::Cell::size_type
MAPITL::Cell::size     () const { return MFnopsList(cell);    }

MAPITL::Cell::size_type
MAPITL::Cell::capacity () const { return MFnopsList(cell);;   }

template<class T>
T
MAPITL::Cell::to () const {
  return MtoC<T>(cell);
}

/*
Is it possible to templetize operators?
template<class T>
T
MAPITL::Cell::operator[] (size_type i) const {
  return MtoC<T>(MFgetList(&c, i));
}

template<class T>
Reference<T>
MAPITL::Cell::operator[] (size_type i) {
  return Reference<T>(c,i);
  }*/

MAPITL::Cell::value_type
MAPITL::Cell::operator[] (size_type i) const {
  return Cell(MFgetList(&cell, i));
}

MAPITL::Cell::reference
MAPITL::Cell::operator[] (size_type i) {
  return reference(cell,i);
}

void
MAPITL::Cell::check (size_type i) const {
  if (!(i>=0 && i<MFnopsList(cell))) {
    throw std::out_of_range("MAPITL::Container");
  }
}

template<class T>
T
MAPITL::Cell::at (size_type i) const {
  check(i);
  return MtoC<T>(MFgetList(&cell, i));
}

template<class T>
MAPITL::Reference<T>
MAPITL::Cell::at (size_type i) {
  check(i);
  return Reference<T>(cell, i);
}

template<class T>
MAPITL::Iterator<T>
MAPITL::Cell::begin  () {
  return Iterator<T>(cell, 0);
}

template<class T>
MAPITL::Iterator<T>
MAPITL::Cell::end () {
  return Iterator<T>(cell,MFnopsList(cell));
}

template<class T>
const MAPITL::Iterator<T>
MAPITL::Cell::begin () const {
  return Iterator<T>(cell, 0);
}

template<class T>
const MAPITL::Iterator<T>
MAPITL::Cell::end () const {
  return Iterator<T>(cell, MFnopsList(cell));
}

template<class T>
MAPITL::Cell &
MAPITL::Cell::push_back(T t) {
  long n=MFnopsList(cell);
  MFnopsList(&cell, n+1);
  MFsetList (&cell, n, CtoM(t));
  MFsig(cell);
  return *this;
}

#endif	/* _MAPITL_CELL_H */
