00001 00002 // base.hpp: defines the enum_base type 00003 // 00004 // Copyright 2005 Frank Laub 00005 // Distributed under the Boost Software License, Version 1.0. (See 00006 // accompanying file LICENSE_1_0.txt or copy at 00007 // http://www.boost.org/LICENSE_1_0.txt) 00008 // 00009 00010 #ifndef BOOST_ENUM_BASE_HPP 00011 #define BOOST_ENUM_BASE_HPP 00012 00013 // MS compatible compilers support #pragma once 00014 #if defined(_MSC_VER) && (_MSC_VER >= 1020) 00015 # pragma once 00016 #endif 00017 00018 #include <ostream> 00019 #include <istream> 00020 #include <boost/operators.hpp> 00021 #include <boost/optional.hpp> 00022 00023 namespace boost { 00024 namespace detail { 00025 00026 template <typename Derived, typename ValueType = int> 00027 class enum_base 00028 : private boost::totally_ordered<Derived> 00029 { 00030 public: 00031 typedef enum_base<Derived, ValueType> this_type; 00032 typedef size_t index_type; 00033 typedef ValueType value_type; 00034 typedef enum_iterator<Derived> const_iterator; 00035 typedef boost::optional<Derived> optional; 00036 00037 public: 00038 enum_base() {} 00039 enum_base(index_type index) : m_index(index) {} 00040 00041 static const_iterator begin() 00042 { 00043 return const_iterator(0); 00044 } 00045 00046 static const_iterator end() 00047 { 00048 return const_iterator(Derived::size); 00049 } 00050 00051 static optional get_by_value(value_type value) 00052 { 00053 for(index_type i = 0; i < Derived::size; ++i) 00054 { 00055 typedef boost::optional<value_type> optional_value; 00056 optional_value cur = Derived::values(enum_cast<Derived>(i)); 00057 if(value == *cur) 00058 return Derived(enum_cast<Derived>(i)); 00059 } 00060 return optional(); 00061 } 00062 00063 static optional get_by_index(index_type index) 00064 { 00065 if(index >= Derived::size) return optional(); 00066 return optional(enum_cast<Derived>(index)); 00067 } 00068 00069 const char* str() const 00070 { 00071 const char* ret = Derived::names(enum_cast<Derived>(m_index)); 00072 BOOST_ASSERT(ret); 00073 return ret; 00074 } 00075 00076 value_type value() const 00077 { 00078 typedef boost::optional<value_type> optional_value; 00079 optional_value ret = Derived::values(enum_cast<Derived>(this->m_index)); 00080 BOOST_ASSERT(ret); 00081 return *ret; 00082 } 00083 00084 index_type index() const 00085 { 00086 return m_index; 00087 } 00088 00089 bool operator == (const this_type& rhs) const 00090 { 00091 return m_index == rhs.m_index; 00092 } 00093 00094 bool operator < (const this_type& rhs) const 00095 { 00096 value_type lhs_value = value(); 00097 value_type rhs_value = rhs.value(); 00098 if(lhs_value == rhs_value) 00099 return m_index < rhs.m_index; 00100 return lhs_value < rhs_value; 00101 } 00102 00103 protected: 00104 friend class enum_iterator<Derived>; 00105 index_type m_index; 00106 }; 00107 00108 template <typename D, typename V> 00109 std::ostream& operator << (std::ostream& os, const enum_base<D, V>& rhs) 00110 { 00111 return (os << rhs.str()); 00112 } 00113 00114 template <typename D, typename V> 00115 std::istream& operator >> (std::istream& is, enum_base<D, V>& rhs) 00116 { 00117 std::string str; 00118 is >> str; 00119 BOOST_DEDUCED_TYPENAME D::optional ret = D::get_by_name(str.c_str()); 00120 if(ret) 00121 rhs = *ret; 00122 else 00123 is.setstate(std::ios::badbit); 00124 return is; 00125 } 00126 00127 } // detail 00128 } // boost 00129 00130 #endif