#ifndef ASTL_CLASS_STATE_REF
#define ASTL_CLASS_STATE_REF

#include <set>
#include <functional>

#ifdef WIN32
using namespace std;
#endif

template <class T, class Compare>
struct interne
{
  set<T, Compare> ensemble;
  unsigned long   references;

  interne() : references(1)
  { }

  template <class InputIterator>
  interne(InputIterator first, InputIterator last) 
    : ensemble(first, last), references(1)
  { }
};

template <class T, class Compare>
class state_ref
{
  interne<T, Compare> *i;

public:
    state_ref() : i(new interne<T, Compare>)
    { }

    template <class InputIterator>
    state_ref(InputIterator first, InputIterator last) 
      : i(new interne<T, Compare>(first, last))
    { }

    state_ref(const state_ref &x)
    {
      i = x.i;
      ++(i->references);
    }

    bool operator == (const state_ref &r) const {
      return (i == r.i || i->ensemble == r.i->ensemble);
    }

    state_ref& operator = (const state_ref &r)
    {
      if (i != r.i)
      {
        if (--(i->references) == 0)
          delete i;
        i = r.i;
        ++(i->references);
      }
      return (*this);
    }

    ~state_ref()
    {
      cout << "state_ref::~state_ref" << endl;
      if (--(i->references) == 0)
        delete i;
    }

    typedef set<T, Compare> Set;
    typedef state_ref       self;

    typedef Set::key_type               key_type; 
    typedef Set::value_type             value_type; 
    typedef Set::key_compare            key_compare; 
    typedef Set::value_compare          value_compare; 
    typedef Set::reference              reference; 
    typedef Set::const_reference        const_reference; 
    typedef Set::iterator               iterator; 
    typedef Set::const_iterator         const_iterator; 
    typedef Set::reverse_iterator       reverse_iterator; 
    typedef Set::const_reverse_iterator const_reverse_iterator; 
    typedef Set::size_type              size_type; 
    typedef Set::difference_type        difference_type; 

    iterator begin() {
      return (i->ensemble.begin());
    }
    iterator end() {
      return (i->ensemble.end());
    }
    const_iterator begin() const {
      return (i->ensemble.begin());
    }
    const_iterator end() const {
      return (i->ensemble.end());
    }
    reverse_iterator rbegin() {
      return (i->ensemble.rbegin());
    }
    reverse_iterator rend() {
      return (i->ensemble.rend());
    }
    const_reverse_iterator rbegin() const {
      return (i->ensemble.rbegin());
    }
    const_reverse_iterator rend() const {
      return (i->ensemble.rend());
    }

    bool empty() const {
      return (i->ensemble.empty());
    }

    size_type size() const {
      return (i->ensemble.size());
    }

    size_type max_size() const {
      return (i->ensemble.max_size());
    }

    void clear() {
      i->ensemble.clear();
    }
    
    pair<iterator,bool> insert(const value_type &x) {
 //     cout << "stat_ref::insert " << x << endl;
      return (i->ensemble.insert(x));
    }

    iterator insert(iterator position, const value_type &x) {
      return (i->ensemble.insert(position, x));
    }

    template <class InputIterator>
    void insert(InputIterator first, InputIterator last) {
      i->ensemble.insert(first, last);
    }

    void erase(iterator position) {
      i->ensemble.erase(position);
    }

    size_type erase(const key_type &k) {
      return (i->ensemble.erase(k));
    }

    template <class InputIterator>
    void erase(InputIterator first, InputIterator last) {
      i->ensemble.erase(first, last);
    }

    void swap(self &x) {
      std::swap(i, x.i);
    }

    key_compare key_comp() const {
      return (i->ensemble.key_comp());
    }

    value_compare value_comp() const {
      return (i->ensemble.value_comp());
    }

    iterator find(const key_type &k) const {
      return (i->ensemble.find(k));
    }

    size_type count(const key_type &k) const {
      return (i->ensemble.count(k));
    }

    iterator lower_bound(const key_type &k) const {
      return (i->ensemble.lower_bound(k));
    }

    iterator upper_bound(const key_type &k) const {
      return (i->ensemble.upper_bound(k));
    }

    pair<iterator,iterator> equal_range(const key_type &k) const {
      return (i->ensemble.equal_range(k));
    }

    bool operator < (const self &x) const {
      return (i->ensemble < x.i->ensemble);
    }
};

#endif
