// -*- c++ -*-
#ifndef HUGO_MAPSKELETON_H
#define HUGO_MAPSKELETON_H

///\file
///\brief Map concepts checking classes for testing and documenting.

namespace hugo {

  /// The namespace of HUGOlib concepts and concept checking classes
  namespace skeleton {
  
    /// Readable map concept
    template<typename K, typename T>
    class ReadableMap
    {
    public:
      /// Map's key type.
      typedef K KeyType;    
      /// Map's value type. (The type of objects associated with the keys).
      typedef T ValueType;

      /// Returns the value associated with a key.
      ValueType operator[](const KeyType &k) const {return ValueType();}

      /// Copy contsructor. (optional)
      ReadableMap(const ReadableMap&) {}
      /// Assignment operator. (optional)
      ReadableMap& operator=(const ReadableMap&) {return *this;}

      ReadableMap() {}
    };


    /// Writable map concept
    template<typename K, typename T>
    class WritableMap
    {
    public:
      /// Map's key type.
      typedef K KeyType;    
      /// Map's value type. (The type of objects associated with the keys).
      typedef T ValueType;

      /// Sets the value associated with a key.
      void set(const KeyType &k,const ValueType &t) {}

      WritableMap() {}
    };

    ///Read/Writeable map concept
    template<typename K, typename T>
    class ReadWritableMap : public ReadableMap<K,T>,
			    public WritableMap<K,T>
    {
    public:
      /// Map's key type.
      typedef K KeyType;    
      /// Map's value type. (The type of objects associated with the keys).
      typedef T ValueType;

      /// Returns the value associated with a key.
      ValueType operator[](const KeyType &k) const {return ValueType();}
      /// Sets the value associated with a key.
      void set(const KeyType &k,const ValueType &t) {}

      /// Copy contsructor. (optional)
      ReadWritableMap(const ReadWritableMap&) {}
      /// Assignment operator. (optional)
      ReadWritableMap& operator=(const ReadWritableMap&) {return *this;}

      /// Facility to define a map with an other value type (optional)
      template<typename T1>
      struct rebind {
	/// The type of a map with the given value type
	typedef ReadWritableMap<K,T1> other;
      };
      /// @brief Constructor that copies all keys from the other map and
      /// assigns to them a default value (optional)
      template<typename T1>
      ReadWritableMap(const ReadWritableMap<K,T1> &map, const ValueType &v) {}

      ReadWritableMap() {}
    };
  
  
    ///Dereferable map concept
    template<typename K, typename T>
    class DereferableMap : public ReadWritableMap<K,T>
    {
    public:
      /// Map's key type.
      typedef K KeyType;    
      /// Map's value type. (The type of objects associated with the keys).
      typedef T ValueType;
      /// Map's reference type. (Reference to an object associated with a key)
      typedef ValueType& ReferenceType;
      /// Map's const reference type.
      typedef const ValueType& ConstReferenceType;

      ///Returns a reference to the value associated to a key.
      ReferenceType operator[](const KeyType &i);
      ///Returns a const reference to the value associated to a key.
      ConstReferenceType operator[](const KeyType &i) const;
      /// Sets the value associated with a key.
      void set(const KeyType &k,const ValueType &t) { operator[](k)=t; }

      /// Copy contsructor. (optional)
      DereferableMap(const DereferableMap&) {}
      /// Assignment operator. (optional)
      DereferableMap& operator=(const DereferableMap&) {return *this;}

      /// Facility to define a map with an other value type (optional)
      template<typename T1>
      struct rebind {
	/// The type of a map with the given value type
	typedef DereferableMap<K,T1> other;
      };
      /// @brief Constructor that copies all keys from the other map and
      /// assigns to them a default value (optional)
      template<typename T1>
      DereferableMap(const DereferableMap<K,T1> &map, const ValueType &v) {}

      DereferableMap() {}
    };


  }
}
#endif // HUGO_MAPSKELETON_H
