#if     !defined(_ENUM_H)

#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <sstream>
#include <limits>

#include <alma/Enumtcl/enum_set.hpp>
#include <alma/Enumtcl/enum_map.hpp>

template< typename enum_type, 
	  typename val_type,
	  typename set_traits=enum_set_traits<enum_type>,
	  typename map_traits=enum_map_traits<enum_type,val_type> >
class EnumSetVal
{
public:
  EnumSetVal()
  {
    reset();
  }
  EnumSetVal(enum_type setting)
  {
    setOnly(setting);
  }
  EnumSetVal &operator&=(const EnumSetVal &rhs)
  {
    bits &= rhs.bits;
    return *this;
  }
  EnumSetVal &operator|=(const EnumSetVal &rhs)
  {
    bits |= rhs.bits;
    return *this;
  }
  bool less (const EnumSetVal &rhs){
    if(bits.to_ulong()<rhs.bits.to_ulong())return true;
    return false;
  }
  bool operator!= (const EnumSetVal &rhs)
  {
    if(bits.to_ulong()==rhs.bits.to_ulong())return false;
    return true;
  }
  bool operator== (const EnumSetVal &rhs)
  {
    if(bits.to_ulong()==rhs.bits.to_ulong())return true;
    return false;
  }
  EnumSetVal &operator^=(const EnumSetVal &rhs)
  {
    bits ^= rhs.bits;
    return *this;
  }
  std::size_t count() const
  {
    return bits.count();
  }
  std::size_t size() const
  {
    return bits.size();
  }
  bool operator[](enum_type testing) const
  {
    return bits.test(to_bit(testing));
  }
  bool only(enum_type testing) const
  {
    if(count()!=1)return false;
    return bits.test(to_bit(testing));
  }
  bool operator^(enum_type testing) const   // xor operator (^ Python bitwise operator) 
  {
    if(only(testing))return true;
    if(bits.test(to_bit(testing)))return false;
    return true;
  }

  EnumSetVal &set()
  {
    bits.set();
    return *this;
  }
  EnumSetVal &setOnly(enum_type setting)
  {
    bits.reset();
    bits.set(to_bit(setting), true);
    return *this;
  }
  EnumSetVal &set(enum_type setting, bool value = true)
  {
    if(set_traits::maxset<set_traits::count)bits.reset();
    bits.set(to_bit(setting), value);
    return *this;
  }
  EnumSetVal &set(std::vector<enum_type> setting, bool value = true)
  {
    if(set_traits::maxset<set_traits::count)bits.reset();
    unsigned int nmax=setting.size();
    if(nmax>set_traits::maxset)nmax=set_traits::maxset;
    for(unsigned int n=0; n<nmax; n++)
      bits.set(to_bit(setting[n]), value);
    return *this;
  }
  EnumSetVal &set(std::vector<std::string> names, bool /* value = true */)
  {
    // value is not used here, commented out above to silence a compiler warning
    bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator 
      it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::vector<std::string>::iterator iv, ivb=names.begin(), ive=names.end();
    for(iv=ivb; iv!=ive; ++iv)
      for(it=itb; it!=ite; ++it)if(it->second.str()==*iv)
	bits.set(to_bit(it->first));
    return *this;
  }


  EnumSetVal &reset()
  {
    bits.reset();
    return *this;
  }
  EnumSetVal &reset(enum_type resetting)
  {
    bits.reset(to_bit(resetting));
    return *this;
  }
  EnumSetVal &flip()
  {
    bits.flip();
    return *this;
  }
  EnumSetVal &flip(enum_type flipping)
  {
    bits.flip(to_bit(flipping));
    return *this;
  }
  EnumSetVal operator~() const
  {
    return EnumSetVal(*this).flip();
  }
  bool any() const
  {
    return bits.any();
  }
  bool none() const
  {
    return bits.none();
  }
  static std::vector<enum_type> enumEnumerators()
  {
    typename std::vector<enum_type> e;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)e.push_back(it->first);
    return e;
  }
  static std::set<std::string> enumMemberSet()
  {
    std::set<std::string> s;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)s.insert(it->second.str());
    return s;
  }
  static std::vector<std::string> enumMemberList(){
    std::vector<std::string> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.str());
    return v;
  }

  static std::vector<val_type> enumValues(){
    std::vector<val_type> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.val());
    return v;
  }

  static unsigned int enumNum(){
    return map_traits::m_.size();
  }

  static std::string doc(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.desc();
  }

  static val_type val(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.val();
  }

  /** Methods using bits and associated with enum_map */
  std::vector<int> id(){
    std::vector<int> v_id;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])v_id.push_back(it->second.id());
    return v_id;
  }

  std::string str(){
    return toString();
  }

  std::string toString(){
    std::ostringstream os;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])os<<it->second.str()<<" ";
    if(os.str().length())
      return os.str().substr(0,os.str().length()-1);
    else
      return os.str();
  }
  std::vector<enum_type> toEnumType(){
    std::vector<enum_type> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])v.push_back(it->first);
    return v;
  }
  // Method to define only when traits::maxset > 1
   EnumSetVal<enum_type,val_type>& fromString(std::vector<std::string> s){
//   EnumSetVal<enum_type,val_type>& fromString(std::vector<std::string> s, bool reset){
//     int id;
//     int nmax=s.size();
//     if(reset)bits.reset();
//     if(nmax>set_traits::maxset)nmax=set_traits::maxset;
//     int k=0;
//     for(int n=0; n<nmax; n++){
//       id = map_traits::fromStringToInt(s[n]);
//       if(id!=numeric_limits<int>::max())
// 	bits.set(enum_type(id));
//     }
//     return *this;
    unsigned int nmax=s.size(); std::cout<<"nmax="<<nmax<<std::endl; 
    bits.reset();
    if(nmax>set_traits::maxset)
      std::cout<<"WARNING: the input number of enumerators, "<<nmax<<",exceeds the maximum number, "
	       <<set_traits::maxset<<",  allowed for a compound with this EnumSet<"
	       <<map_traits::typeName_<<"> type."<<std::endl;
    bool ok;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    unsigned int numSet=0;
    for(unsigned int n=0; n<nmax; n++){
      ok=false;
      for(it=itb;it!=ite;++it)
	if(s[n]==it->second.str()){ok=true; break;}
      if(ok){
	bits.set(it->first);
	numSet++;
      }else{
	std::cout<<"WARNING: "<<s[n]<<" is not a valid enumerator name for this enumeration "
		 <<map_traits::typeName_<<std::endl;
      }
      if(numSet==set_traits::maxset)break;
    }
    std::cout<<"numSet="<<numSet<<std::endl;
    return *this;
  }
  // Method useful when maxset>1.
  EnumSetVal<enum_type,val_type>& fromString(std::string s, bool reset){
    if(reset)bits.reset();
    int id = map_traits::fromStringToInt(s);
    if(id==std::numeric_limits<int>::max())
      bits.reset();
    else
      bits.set(enum_type(id));
    return *this;
  }
  // Method to define only when traits::maxset > 1
  EnumSetVal<enum_type,val_type>& fromString(std::string setting)
  {
    // TODO traiter le cas de 2 enumerators comme CORRECTED and UNCORRECTED  car ==> blancs avt ou apres 
    unsigned int nmax=set_traits::maxset;
    if(nmax<set_traits::count)bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb;it!=ite;++it)
      if(setting.find(it->second.str())!=std::string::npos)bits.set(it->first);
    return *this;
  }
  // Method to get a vector of the names of the enumerators set on.
  std::vector<std::string> names()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::vector<std::string> v_s;
    unsigned int numset=0; 
    for(it=itb;it!=ite;++it){
      if(bits.test(to_bit(it->first))){
	v_s.push_back(it->second.str());
	numset++; 
      }
      if(set_traits::maxset==numset)break;
      if(set_traits::last==it->first)break;
    }
    return v_s;
  }

  // Method to get the set of enumerators
  std::set<enum_type> enumSet()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::set<enum_type> s_et;
    for(it=itb;it!=ite;++it)
      if(bits.test(to_bit(it->first)))s_et.insert(it->first);
    return s_et;
  }    
  // Method to get the set of enumerator values
  std::vector<val_type> enumVal()
  {
    std::vector<val_type> v_s;
    std::set<enum_type> s_et=enumSet();
    typename std::set<enum_type>::iterator its, itsb(s_et.begin()), itse(s_et.end());
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf;
    for(its=itsb; its!=itse; ++its){
      itf=map_traits::m_.find(*its);
      v_s.push_back(itf->second.val());
    }
    return v_s;
  }    


protected:
  static std::size_t to_bit(enum_type value)
  {
    return (value - set_traits::first) / set_traits::step;
  }
  std::bitset<set_traits::count> bits;
};


template<typename enum_type,
	 typename val_type=void, 
	 typename set_traits=enum_set_traits<enum_type>,
	 typename map_traits=enum_map_traits<enum_type,val_type> >
class EnumSet
{
public:
  EnumSet()
  {
    reset();
  }
  EnumSet(enum_type setting)
  {
    setOnly(setting);
  }
  EnumSet &operator&=(const EnumSet &rhs)
  {
    bits &= rhs.bits;
    return *this;
  }
  EnumSet &operator|=(const EnumSet &rhs)
  {
    bits |= rhs.bits;
    return *this;
  }
  bool less (const EnumSet &rhs){
    if(bits.to_ulong()<rhs.bits.to_ulong())return true;
    return false;
  }
  bool operator!= (const EnumSet &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return false;
    return true;
  }
  bool operator== (const EnumSet &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return true;
    return false;
  }
  EnumSet &operator^=(const EnumSet &rhs)
  {
    bits ^= rhs.bits;
    return *this;
  }
  std::size_t count() const
  {
    return bits.count();
  }
  std::size_t size() const
  {
    return bits.size();
  }
  bool operator[](enum_type testing) const
  {
    return bits.test(to_bit(testing));
  }
  bool only(enum_type testing) const
  {
    if(count()!=1)return false;
    return bits.test(to_bit(testing));
  }
  bool operator^(enum_type testing) const   // xor operator (^ Python bitwise operator) 
  {
    if(only(testing))return true;
    if(bits.test(to_bit(testing)))return false;
    return true;
  }

  EnumSet &set()
  {
    bits.set();
    return *this;
  }
  EnumSet &setOnly(enum_type setting)
  {
    bits.reset();
    bits.set(to_bit(setting), true);
    return *this;
  }
//   error: call of overloaded `set(StokesParameter)'
//   EnumSet &set(enum_type setting)
//   {
//     bits.set(to_bit(setting), true);
//     return *this;
//   }
  EnumSet &set(enum_type setting, bool value = true)
  {
    if(set_traits::maxset<set_traits::count)bits.reset();
    bits.set(to_bit(setting), value);
    return *this;
  }
  EnumSet &set(std::vector<enum_type> setting, bool value = true)
  {
//     if(set_traits::maxset<set_traits::count)bits.reset();
    bits.reset();
    unsigned int nmax=setting.size();
    if(nmax>set_traits::maxset)nmax=set_traits::maxset;
    for(unsigned int n=0; n<nmax; n++)
      bits.set(to_bit(setting[n]), value);
    return *this;
  }

  EnumSet &set(std::vector<std::string> names, bool /* value = true */)
  {
    // value is not used here, commented out above to silence a compiler warning
    bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator 
      it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::vector<std::string>::iterator iv, ivb=names.begin(), ive=names.end();
    for(iv=ivb; iv!=ive; ++iv)
      for(it=itb; it!=ite; ++it)if(it->second.str()==*iv)
	bits.set(to_bit(it->first));
    return *this;
  }

  EnumSet &reset()
  {
    bits.reset();
    return *this;
  }
  EnumSet &reset(enum_type resetting)
  {
    bits.reset(to_bit(resetting));
    return *this;
  }
  EnumSet &flip()
  {
    bits.flip();
    return *this;
  }
  EnumSet &flip(enum_type flipping)
  {
    bits.flip(to_bit(flipping));
    return *this;
  }
  EnumSet operator~() const
  {
    return EnumSet(*this).flip();
  }
  bool any() const
  {
    return bits.any();
  }
  bool none() const
  {
    return bits.none();
  }
  static void enumEnumerators(std::vector<enum_type>& v)
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->first);
    return;
  }
  static std::set<std::string> enumMemberSet()
  {
    std::set<std::string> s;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)s.insert(it->second.str());
    return s;
  }
  static std::vector<std::string> enumMemberList(){
    std::vector<std::string> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.str());
    return v;
  }
  static std::string doc(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.desc();
  }

//   static std::string val(enum_type t){
//     typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
//     return itf->second.val();
//   }

  /** Methods using bits and associated with enum_map */
  std::vector<int> id(){
    std::vector<int> v_id;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])v_id.push_back(it->second.id());
    return v_id;
  }
  std::string str(){
    return toString();
  }
  std::string toString(){
    std::ostringstream os;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])os<<it->second.str()<<" ";
    if(os.str().length())
      return os.str().substr(0,os.str().length()-1);
    else
      return os.str();
  }
  std::vector<enum_type> toEnumType(){
    std::vector<enum_type> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])v.push_back(it->first);
    return v;
  }
  // Method to define only when traits::maxset > 1
  EnumSet<enum_type,val_type>& fromString(std::vector<std::string> s){
//   EnumSet<enum_type,val_type>& fromString(std::vector<std::string> s, bool reset){
//     int id;
//     int nmax=s.size();
//     if(reset)bits.reset();
//     if(nmax>set_traits::maxset)nmax=set_traits::maxset;
//     int k=0;
//     for(int n=0; n<nmax; n++){
//       id = map_traits::fromStringToInt(s[n]);
//       if(id!=numeric_limits<int>::max())
// 	bits.set(enum_type(id));
//     }
//     return *this;
    unsigned int nmax=s.size(); std::cout<<"nmax="<<nmax<<std::endl; 
    bits.reset();
    if(nmax>set_traits::maxset)
      std::cout<<"WARNING: the input number of enumerators, "<<nmax<<",exceeds the maximum number, "
	       <<set_traits::maxset<<",  allowed for a compound with this EnumSet<"
	       <<map_traits::typeName_<<"> type."<<std::endl;
    bool ok;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    int numSet=0;
    for(int n=0; n<nmax; n++){
      ok=false;
      for(it=itb;it!=ite;++it)
	if(s[n]==it->second.str()){ok=true; break;}
      if(ok){
	bits.set(it->first);
	numSet++;
      }else{
	std::cout<<"WARNING: "<<s[n]<<" is not a valid enumerator name for this enumeration "
		 <<map_traits::typeName_<<std::endl;
      }
      if(numSet==set_traits::maxset)break;
    }
    std::cout<<"numSet="<<numSet<<std::endl;
    return *this;
  }
  // Method useful when maxset>1.
  EnumSet<enum_type,val_type>& fromString(std::string s, bool reset){
    if(reset)bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb;it!=ite;++it)
      if(s.find(it->second.str())!=std::string::npos)bits.set(it->first);
    return *this;
  }
  // Method to define only when traits::maxset > 1
  EnumSet <enum_type,val_type>& fromString(std::string setting)
  {
    // TODO traiter le cas de 2 enumerators comme CORRECTED and UNCORRECTED  car ==> blancs avt ou apres 
    unsigned int nmax=set_traits::maxset;
    if(nmax<set_traits::count)bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb;it!=ite;++it)
      if(setting.find(it->second.str())!=std::string::npos)bits.set(it->first);
    return *this;
  }
  // Method to get a vector of the names of the enumerators set on.
  std::vector<std::string> names()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::vector<std::string> v_s;
    unsigned int numset=0;
    for(it=itb;it!=ite;++it){
      if(bits.test(to_bit(it->first))){
	v_s.push_back(it->second.str());
	numset++; 
      }
      if(set_traits::maxset==numset)break;
      if(set_traits::last==it->first)break;
    }
    return v_s;  
  }
  // Method to get the set of enumerators
  std::set<enum_type> enumSet()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::set<enum_type> s_et;
    for(it=itb;it!=ite;++it)
      if(bits.test(to_bit(it->first)))s_et.insert(it->first);
    return s_et;
  }    
//   // Method to get the set of enumerator values
//   std::vector<std::string> enumVal()
//   {
//     std::vector<std::string> v_s;
//     std::set<enum_type> s_et=enumSet();
//     typename std::set<enum_type>::iterator its, itsb(s_et.begin()), itse(s_et.end());
//     typename std::map<enum_type,EnumPar<val_type> >::iterator itf;
//     for(its=itsb; its!=itse; ++its){
//       itf=map_traits::m_.find(*its);
//       v_s.push_back(itf->second.val());
//     }
//     return v_s;
//   }    


protected:
  static std::size_t to_bit(enum_type value)
  {
    return (value - set_traits::first) / set_traits::step;
  }
  std::bitset<set_traits::count> bits;
};



template< typename enum_type, 
	  typename val_type,
	  typename set_traits=enum_set_traits<enum_type>,
	  typename map_traits=enum_map_traits<enum_type,val_type> >
class EnumVal
{
public:
  EnumVal()
  {
  }
  EnumVal(enum_type setting)
  {
    set(setting);
  }
  EnumVal &operator&=(const EnumVal &rhs)
  {
    bits &= rhs.bits;
    return *this;
  }
  EnumVal &operator|=(const EnumVal &rhs)
  {
    bits |= rhs.bits;
    return *this;
  }
  bool less (const EnumVal &rhs){
    if(bits.to_ulong()<rhs.bits.to_ulong())return true;
    return false;
  }
  bool operator!= (const EnumVal &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return false;
    return true;
  }
  bool operator== (const EnumVal &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return true;
    return false;
  }
  EnumVal &operator^=(const EnumVal &rhs)
  {
    bits ^= rhs.bits;
    return *this;
  }
  std::size_t count() const
  {
    return bits.count();
  }
  std::size_t size() const
  {
    return bits.size();
  }
  bool operator[](enum_type testing) const
  {
    return bits.test(to_bit(testing));
  }
  bool only(enum_type testing) const
  {
    if(count()!=1)return false;
    return bits.test(to_bit(testing));
  }
  bool operator^(enum_type testing) const   // xor operator (^ Python bitwise operator) 
  {
    if(only(testing))return true;
    if(bits.test(to_bit(testing)))return false;
    return true;
  }

  EnumVal &set()
  {
    bits.set();
    return *this;
  }
  /** Store a boolean value as the new value for bit at position setting.
   * @pre if the number if bits set is smaller than the maximum
   *      allowed number of bit set then the bitset is first reset
   * @param setting the position in the bitset where "value" must be stored
   * @param value the boolean value to store
   * @post all positions are unset (i.e. false), except the position "setting"
   *       would value=true
   */
  EnumVal &set(enum_type setting, bool value = true)
  {
    if(set_traits::maxset<set_traits::count)bits.reset();
    bits.set(to_bit(setting), value);
    return *this;
  }
  /** Store "true" at a set of positions.
   * @param setting vector of positions in the bitset (Order positions 
   *        are counted from the rightmost bit, which is order position 0.
   * @post the value "true" stored at these positions in the bitset.
   */
  EnumVal &set(std::vector<enum_type> setting)
  {
    bits.reset();
    unsigned int nmax=setting.size();
    if(nmax>set_traits::maxset)nmax=set_traits::maxset;
    for(int n=1; n<nmax; n++)
      bits.set(to_bit(setting[n]),true);
    return *this;
  }

  EnumVal &reset()
  {
    bits.reset();
    return *this;
  }
  EnumVal &reset(enum_type resetting)
  {
    bits.reset(to_bit(resetting));
    return *this;
  }
  EnumVal &flip()
  {
    bits.flip();
    return *this;
  }
  EnumVal &flip(enum_type flipping)
  {
    bits.flip(to_bit(flipping));
    return *this;
  }
  EnumVal operator~() const
  {
    return EnumVal(*this).flip();
  }
  bool any() const
  {
    return bits.any();
  }
  bool none() const
  {
    return bits.none();
  }
  static std::set<std::string> enumMemberSet()
  {
    std::set<std::string> s;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)s.insert(it->second.str());
    return s;
  }
  static std::vector<std::string> enumMemberList(){
    std::vector<std::string> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.str());
    return v;
  }

  static std::vector<val_type> enumValues(){
    std::vector<val_type> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.val());
    return v;
  }

  static unsigned int enumNum(){
    return map_traits::m_.size();
  }

  static std::string doc(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.desc();
  }

  static val_type val(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.val();
  }

  // Method to get the name of the enumerator set on, if set, else return empty string
  std::string name()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::string s="";
    for(it=itb;it!=ite;++it){
      if(bits.test(to_bit(it->first)))
	return it->second.str();
      if(set_traits::last==it->first)break;
    }
    return s;
  }
  /** Methods using bits and associated with enum_map */
  int id(){
    int id;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])id=it->second.id();
    return id;
  }
  std::string str(){
    return toString();
  }
  std::string toString(){
    std::ostringstream os;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])os<<it->second.str();
    return os.str();
  }
  enum_type toEnumType(){
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])return it->first;
    std::cout<<"ERROR: state with no enumerator set"<<std::endl;
  }

  EnumVal<enum_type,val_type>& fromString(std::string setting)
  {
    bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb;it!=ite;++it)
      if(setting.find(it->second.str())!=std::string::npos)bits.set(it->first);
    return *this;
  }
  // Method to get the enumerator value for the bit currently set
  std::vector<val_type> enumVal()
  {
    std::vector<val_type> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator 
      it, 
      itb=map_traits::m_.begin(), 
      ite=map_traits::m_.end();
    for(it=itb; it!=ite; ++it)
      if(bits.test(it->first))v.push_back(it->second.val());
    return v;
  }    


protected:
  static std::size_t to_bit(enum_type value)
  {
    return (value - set_traits::first) / set_traits::step;
  }
  std::bitset<set_traits::count> bits;
};


template<typename enum_type,
	 typename val_type=void, 
	 typename set_traits=enum_set_traits<enum_type>,
	 typename map_traits=enum_map_traits<enum_type,val_type> >
class Enum
{
public:
  Enum()
  {
  }
  Enum(const enum_type setting)
  {
    set(setting);
  }
  Enum &operator&=(const Enum &rhs)
  {
    bits &= rhs.bits;
    return *this;
  }
  Enum &operator|=(const Enum &rhs)
  {
    bits |= rhs.bits;
    return *this;
  }
  bool less (const Enum &rhs){
    if(bits.to_ulong()<rhs.bits.to_ulong())return true;
    return false;
  }
  bool operator!= (const Enum &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return false;
    return true;
  }
  bool operator== (const Enum &rhs){
    if(bits.to_ulong()==rhs.bits.to_ulong())return true;
    return false;
  }
  Enum &operator^=(const Enum &rhs)
  {
    bits ^= rhs.bits;
    return *this;
  }
  std::size_t count() const
  {
    return bits.count();
  }
  std::size_t size() const
  {
    return bits.size();
  }
  bool operator[](enum_type testing) const
  {
    return bits.test(to_bit(testing));
  }
  bool only(enum_type testing) const
  {
    if(count()!=1)return false;
    return bits.test(to_bit(testing));
  }
  bool operator^(enum_type testing) const   // xor operator (^ Python bitwise operator) 
  {
    if(only(testing))return true;
    if(bits.test(to_bit(testing)))return false;
    return true;
  }

  Enum &set()
  {
    bits.set();
    return *this;
  }
  Enum &set(enum_type setting)
  {
    bits.reset();
    bits.set(to_bit(setting), true);
    return *this;
  }
  Enum &reset()
  {
    bits.reset();
    return *this;
  }
  Enum &reset(enum_type resetting)
  {
    bits.reset(to_bit(resetting));
    return *this;
  }
  Enum &flip()
  {
    bits.flip();
    return *this;
  }
  Enum &flip(enum_type flipping)
  {
    bits.flip(to_bit(flipping));
    return *this;
  }
  Enum operator~() const
  {
    return Enum(*this).flip();
  }
  bool any() const
  {
    return bits.any();
  }
  bool none() const
  {
    return bits.none();
  }
  static std::set<std::string> enumMemberSet()
  {
    std::set<std::string> s;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)s.insert(it->second.str());
    return s;
  }
  static std::vector<std::string> enumMemberList(){
    std::vector<std::string> v;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)v.push_back(it->second.str());
    return v;
  }
  static std::string doc(enum_type t){
    typename std::map<enum_type,EnumPar<val_type> >::iterator itf(map_traits::m_.find(t));
    return itf->second.desc();
  }

  // Method to get the name of the enumerator set on, if set, else return empty string
  std::string name()
  {
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    std::string s="";
    for(it=itb;it!=ite;++it){
      if(bits.test(to_bit(it->first)))
	return it->second.str();
      if(set_traits::last==it->first)break;
    }
    return s;
  }

  unsigned int hash() {
    std::string s = str();
    unsigned int hash = 0;
    for(size_t i = 0; i < s.size(); ++i) 
      hash = 65599 * hash + s[i];
    return hash ^ (hash >> 16);
  }

  /** Methods using bits and associated with enum_map */
  int id(){
    int id;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])id=it->second.id();
    return id;
  }
  std::string str(){
    return toString();
  }
  std::string toString(){
    std::ostringstream os;
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])os<<it->second.str();
    return os.str();
  }
  enum_type toEnumType() const{
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb; it!=ite; ++it)
      if(bits[it->first])return it->first;
    std::cout<<"ERROR: state with no enumerator set"<<std::endl;
  }
  // Method useful when maxset>1.
  Enum<enum_type,val_type>& fromString(std::string s){
    bits.reset();
    typename std::map<enum_type,EnumPar<val_type> >::iterator it, itb(map_traits::m_.begin()), ite(map_traits::m_.end());
    for(it=itb;it!=ite;++it)
      if(s.find(it->second.str())!=std::string::npos)bits.set(it->first);
    return *this;
  }


protected:
  static std::size_t to_bit(enum_type value)
  {
    return (value - set_traits::first) / set_traits::step;
  }
  std::bitset<set_traits::count> bits;
};



#define _ENUM_H
#endif