Recently I thought of doing it a different way
that I have never seen attempted before.
I want to share the idea here and get some feedback.
My new idea (well, new to me, anyway) is
to have a macro that is used to declare the variable,
as well as macros to declare the class with the
stringify function. It occured to me that if you
always give a value to a enum then that is where the
mapping from enumeration to equivalent string could
take place. There also needs to be a similar macro
to allow new values to be assigned.
My first attempt is below:
#include <iostream>
#include <string>
#include <cstdlib>
#define ENUM_BEGIN(a_class) \
class a_class { public: \
enum a_class##_enum {
#define ENUM_VALUE(a_value) \
a_value##,
#define ENUM_END(a_class) \
}; \
a_class(a_class##_enum value, const std::string& name) \
: m_value(value) \
, m_name(name) \
{ } \
std::string asString() const \
{ \
return m_name; \
} \
int asInteger() const \
{ \
return (int)m_value; \
} \
private: \
a_class##_enum m_value; \
std::string m_name; \
};
#define ENUM_DECLARE(a_class, a_variable, a_value) \
a_class a_variable (a_class::a_value, #a_value)
#define ENUM_ASSIGN(a_class, a_variable, a_value) \
a_variable = a_class(a_class::a_value, #a_value);
int main(int argc, char* argv[])
{
ENUM_BEGIN(e_suit)
e_clubs,
e_hearts,
e_diamonds = 47,
e_spades
ENUM_END(e_suit)
ENUM_DECLARE(e_suit, d, e_diamonds);
ENUM_ASSIGN(e_suit, d, e_spades);
std::cout << "via our macros, value = "
<< d.asString() << ", integer = "
<< d.asInteger() << std::endl;
return EXIT_SUCCESS;
}
Regards,
Andrew Marlow
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
If you're interested in a code generator to make a clean, efficient
enum-class, with stringification (and string->enum conversions too),
you might take a look at enumgen, an open source tool I've started
building. It's biggest "lack" is documentation, but the test
directory has some good examples. The generator is written in Common
Lisp and is only tested on linux, but it generates efficient and
easily readable C++ code that should be portable nearly anywhere (once
it's generated.)
http://enumgen.googlecode.com/
--
Chris
One of my favorite ways:
enum Myenum{
Zero,One,Two,Three
};
std::ostream& operator<<(std::ostream&os,Myenum val){
switch(val){
case Zero: os<<"Zero";break;
case One: os<<"One";break;
case Two: os<<"Two";break;
case Three: os<<"Three";break;
default:
os<<"Unknown Myenum("<<static_cast<int>(val)<<")";
}
return os;
}
and an analgous version for istream
Lance
Hi Andrew,
Interesting approach. The issues I see are:
- it's pretty invasive / finicky to use
- you need a similar ENUM_XXX function to support creation of a
temporary (e.g. to pass to functions)
- there's no way to iterate over or count the enumeration values
- there's no support for values that are ORed together, or flipped
filters ala "~"
- you can't construct the enums when only the numeric value is
available
- you can't support incrementing/decrementing etc. as the string won't
be updated
More generally, I'm interested to morph the discussion a little.
Assuming that an accurate record of identifiers and values is
available, what additional information would be necessary to support
the more complicated uses to which enums are put. For example, a
bitwise OR of 2 enumerations might be used to test that either bit it
set, or that both bits are set - should that kind of data be captured
and the uses supported? My current thought - not explored much - is
that using a notation like:
BENUM(Type, Int = 1, Double = 2, String = 4, Const = 8, ConstInt =
AllOf(Const|Int), Numeric = AnyOf(Int|Double));
would then allow:
a_type.is(ConstInt) to test "value & ConstInt == ConstInt", while
a_type.is(Numeric) tests "value & Numeric"
Does this sound useful? Have to think through similar uses
involving negated filters etc..
Lance: have promised to send Andrew my BENUM solution which you
expressed interest in on the Boost mailing group (been lazy about it
since)... will do so this weekend and post back here when we've
collaborated on a couple optimisation issues and perhaps implemented
the "is" concept mentioned above.
Tony