34 #include <boost/utility/enable_if.hpp>
35 #include <boost/lexical_cast.hpp>
36 #include <boost/mpl/assert.hpp>
47 inline std::size_t OneBits(
unsigned int num)
49 std::size_t retval = 0;
50 const std::size_t NUM_BITS =
sizeof(num) * 8;
51 for (std::size_t i = 0; i < NUM_BITS; ++i) {
74 #define GG_FLAG_TYPE(name) \
78 struct is_flag_type<name> : boost::mpl::true_ {}; \
83 name() : m_value(0) {} \
84 explicit name(unsigned int value) : \
87 if (1u < detail::OneBits(value)) \
88 throw std::invalid_argument( \
89 "Non-bitflag passed to " #name " constructor"); \
91 bool operator==(name rhs) const \
92 { return m_value == rhs.m_value; } \
93 bool operator!=(name rhs) const \
94 { return m_value != rhs.m_value; } \
95 bool operator<(name rhs) const \
96 { return m_value < rhs.m_value; } \
98 unsigned int m_value; \
99 friend class Flags<name>; \
103 FlagSpec<name>& FlagSpec<name>::instance(); \
105 inline std::ostream& operator<<(std::ostream& os, name n) \
107 os << FlagSpec<name>::instance().ToString(n); \
111 inline std::istream& operator>>(std::istream& is, name& n) \
115 n = FlagSpec<name>::instance().FromString(str); \
122 #define GG_FLAGSPEC_IMPL(name) \
124 FlagSpec<name>& FlagSpec<name>::instance() \
126 static FlagSpec retval; \
148 template <
class FlagType>
159 typedef typename std::set<FlagType>::iterator
iterator;
179 bool contains(FlagType flag)
const
180 {
return find(flag) != end(); }
183 bool permanent(FlagType flag)
const
184 {
return m_permanent.find(flag) != m_permanent.end(); }
188 {
return m_flags.find(flag); }
191 {
return m_flags.begin(); }
194 {
return m_flags.end(); }
198 const std::string& ToString(FlagType flag)
const
200 typename std::map<FlagType, std::string>::const_iterator it = m_strings.find(flag);
201 if (it == m_strings.end())
202 throw UnknownFlag(
"Could not find string corresponding to unknown flag");
207 FlagType FromString(
const std::string& str)
const
209 for (
typename std::map<FlagType, std::string>::const_iterator it = m_strings.begin();
210 it != m_strings.end();
212 if (it->second == str)
215 throw UnknownString(
"Could not find flag corresponding to unknown string");
225 void insert(FlagType flag,
const std::string& name,
bool permanent =
false)
228 bool insert_successful =
230 m_flags.insert(flag).second;
231 assert(insert_successful);
233 m_permanent.insert(flag);
234 m_strings[flag] = name;
241 bool erase(FlagType flag)
244 if (permanent(flag)) {
248 m_permanent.erase(flag);
249 m_strings.erase(flag);
258 std::set<FlagType> m_flags;
259 std::set<FlagType> m_permanent;
260 std::map<FlagType, std::string> m_strings;
264 template <
class FlagType>
267 template <
class FlagType>
268 std::ostream& operator<<(std::ostream& os, Flags<FlagType> flags);
274 template <
class FlagType>
278 struct ConvertibleToBoolDummy {
int _;};
302 m_flags(flag.m_value)
305 throw UnknownFlag(
"Invalid flag with value " + boost::lexical_cast<std::string>(flag.m_value));
313 operator int ConvertibleToBoolDummy::* ()
const
314 {
return m_flags ? &ConvertibleToBoolDummy::_ : 0; }
317 {
return m_flags == rhs.m_flags; }
320 {
return m_flags != rhs.m_flags; }
324 bool operator<(Flags<FlagType> rhs)
const
325 {
return m_flags < rhs.m_flags; }
333 m_flags |= rhs.m_flags;
340 m_flags &= rhs.m_flags;
347 m_flags ^= rhs.m_flags;
353 unsigned int m_flags;
355 friend std::ostream& operator<<<>(std::ostream& os,
Flags<FlagType> flags);
359 template <
class FlagType>
360 std::ostream& operator<<(std::ostream& os, Flags<FlagType> flags)
362 unsigned int flags_data = flags.m_flags;
363 bool flag_printed =
false;
364 for (std::size_t i = 0; i <
sizeof(flags_data) * 8; ++i) {
365 if (flags_data & 1) {
368 os << FlagSpec<FlagType>::instance().ToString(FlagType(1 << i));
378 template <
class FlagType>
388 template <
class FlagType>
394 template <
class FlagType>
400 template <
class FlagType>
401 typename boost::enable_if<
402 is_flag_type<FlagType>,
410 template <
class FlagType>
420 template <
class FlagType>
426 template <
class FlagType>
432 template <
class FlagType>
433 typename boost::enable_if<
434 is_flag_type<FlagType>,
442 template <
class FlagType>
452 template <
class FlagType>
458 template <
class FlagType>
464 template <
class FlagType>
465 typename boost::enable_if<
466 is_flag_type<FlagType>,
474 template <
class FlagType>
488 template <
class FlagType>
489 typename boost::enable_if<
490 is_flag_type<FlagType>,