namespace MAPITL
{
  ////////////////////////////////////////////////////////////////////////////
  // Container<T>: wrapper around a MuPAD DOM_LIST to make it an
  // STL-compatible container.
  ////////////////////////////////////////////////////////////////////////////
  
  // Bugs:
  //
  //  - The only way to modify an element of the container is to
  //    assign to it. For example, m[i]++ is forbidden, whereas
  //	m[i]=m[i]+1 works. Of course, this also holds for iterators,
  //	where *it++ is forbidden whereas *it=*it+1 works.
  //    The reason for this is that MAPI does not allow for in place
  //	modifications, which is relatively reasonnable.

  template<class T>
  class Container {
  private:
    MTcell c;
  public:

    // Standard container typedefs
    
    typedef	  T	      value_type;
    typedef	  size_t      size_type;
    typedef const value_type *const_pointer;
    typedef       Iterator<T> iterator;
    typedef const iterator    const_iterator;
    typedef       Reference<T>reference;
    typedef const reference   const_reference;
    typedef reverse_iterator<const_iterator> const_reverse_iterator;
    typedef reverse_iterator<iterator>	     reverse_iterator;

    // Constructors and destructors
    
    Container(MTcell c_) : c(c_  ) { }
    explicit Container(size_type len);	// Constructor without initialization
    Container(size_type len, T value);	// Constructor with initialization
  
    template<class InputIterator>	// Constructors from iterator
    Container(InputIterator first, InputIterator last);
    template<class InputIterator>
    Container(InputIterator first, InputIterator last, size_type len);
  
    Container(const Container &);	// Copy constructor

    const MTcell cell() const;
    MTcell       cell();
    
    // Assignment
  
    Container& operator= (const Container&);

    // Assignment from iterators
    
    template<class InputIterator>
    Container& assign (InputIterator first, InputIterator last);
    template<class InputIterator>
    Container& assign (InputIterator first, InputIterator last, size_type len);

    // Standard container accessors

    bool      empty    () const;
    size_type size     () const;
    size_type capacity () const;

    // Iterators & Reverse iterators
  
    iterator       	   begin  ();
    iterator       	   end    ();
    const_iterator 	   begin  () const;
    const_iterator 	   end    () const;

    reverse_iterator	   rbegin ();
    reverse_iterator	   rend   ();
    const_reverse_iterator rbegin () const;
    const_reverse_iterator rend   () const;
  
    // Standard random access operators

    value_type operator [] (size_type) const;
    reference  operator [] (size_type);
    value_type at	  (size_type) const;
    reference  at	  (size_type);
    Container& push_back  (value_type);

    // Miscellaneous

    void       check       (size_type) const;
    // Throws exception out_of_range if the index is out of range
    Container& sign()            { MFsig(c); return *this;   }

  };
}
