Classes for enums

C

cronusf

I like the C# style enums a lot. In particular, I like how you
specify the enum type followed by the member name, and I like the
ToString conversion. Has anyone done anything like the following in C+
+ for all their enums:

class Day
{
public:

// allow conversion to int
operator int() const;

// allow conversion from int to Day
Day& operator=(int x);

string ToString()const
{
switch(value)
{
case 0: return "Monday";
case 1: return "Tuesday";
...
}
}

static const int Monday = 0;
static const int Tuesday = 1;
static const int Wednesday = 2;
static const int Thursday = 3;
static const int Friday = 4;
static const int Saturday = 5;
static const int Sunday = 6;

private:
int value;
};

Then you can use syntax like:

Day d = Day::Monday;
cout << d.ToString() << endl;

I think any overhead would be negligible. You could even make it a
template so that the underlying type could be any kind of integer
type. It also seems like it would integrate without any issues into
existing code bases. Any problems with this?
 
J

Jerry Coffin

[ ... ]
std::eek:stream& operator<<(std::eek:stream& out, value_type v) {
switch (v) {
case monday: return out << "monday";
case tuesday: return out << "tuesday";
case wednesday: return out << "wednesday";
case thursday: return out << "thursday";
case friday: return out << "friday";
case saturday: return out << "saturday";
case sunday: return out << "sunday";
default: break;
}
throw std::logic_error( "bad day" );
}

Unless the enumeration is (and needs to be) non-contiguous, I'd consider
something like:

std::eek:stream &operator<<(std::eek:stream &out, value_type v) {
static char const *names[] = {
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday"
};

if (v >= count)
throw std::logic_error("bad day");
return out << names[v];
}
 
V

Vladyslav Lazarenko

std::eek:stream &operator<<(std::eek:stream &out, value_type v) {
    static char const *names[] = {
        "monday",
        "tuesday",
        "wednesday",
        "thursday",
        "friday",
        "saturday",
        "sunday"
    };

    if (v >= count)
        throw std::logic_error("bad day");
    return out << names[v];

}

--
    Later,
    Jerry.

The universe is a figment of its own imagination.

Is that initialization of static array inside operator << thread-safe?
 
J

Jerry Coffin

(e-mail address removed)>, (e-mail address removed)
says...
std::eek:stream &operator<<(std::eek:stream &out, value_type v) {
    static char const *names[] = {
        "monday",
        "tuesday",
        "wednesday",
        "thursday",
        "friday",
        "saturday",
        "sunday"
    };

    if (v >= count)
        throw std::logic_error("bad day");
    return out << names[v];

}

[ ... ]
Is that initialization of static array inside operator << thread-safe?

The current standard doesn't really provide an answer (to anything about
threading), but generally speaking the answer is yes anyway. The part
that would be tricky would be if it was invoked (indirectly?) from the
ctor of a static object, so the code executed before main was invoked --
but with or without threads, you generally need to do some non-standard
things for streams to work under such circumstances, so this doesn't
really change much (if anything).
 
J

James Kanze

(e-mail address removed)>, (e-mail address removed)
says...
std::eek:stream &operator<<(std::eek:stream &out, value_type v) {
static char const *names[] = {
"monday",
"tuesday",
"wednesday",
"thursday",
"friday",
"saturday",
"sunday"
};
if (v >= count)
throw std::logic_error("bad day");
return out << names[v];
}
[ ... ]
Is that initialization of static array inside operator <<
thread-safe?
The current standard doesn't really provide an answer (to
anything about threading), but generally speaking the answer
is yes anyway. The part that would be tricky would be if it
was invoked (indirectly?) from the ctor of a static object, so
the code executed before main was invoked -- but with or
without threads, you generally need to do some non-standard
things for streams to work under such circumstances, so this
doesn't really change much (if anything).

I'm not sure I see the order of initialization issue for a local
variable. The standard doesn't (currently) say anything about
threading, but it does distinguish between static and dynamic
initialization. In a way that means that in practice, static
initialization (as above) doesn't cause any instructions to be
executed, and thus must be thread neutral. (In practice, this
local variable will be initialized before any code, even that in
the constructors of static objects, is executed, by the OS
copying its image from the executable file into memory.)

Of course, if you used an std::vector< std::string > instead of
the C types, the issues would be different.
 
J

James Kanze

I like the C# style enums a lot. In particular, I like how
you specify the enum type followed by the member name,

You mean, the enum introduces a new scope. This will be
supported in the next version of the standard. You will be able
to write:
enum X { a, b, c } ;
to get the current behavior, or
enum class X { a, b, c } ;
to get the scoped behavior.
and I like the ToString conversion.

That's not really the C++ convention (although I'm not sure that
C++ has a real convention for this).
Has anyone done anything like the following in C+ + for all
their enums:
class Day
{
public:
// allow conversion to int
operator int() const;
// allow conversion from int to Day
Day& operator=(int x);
string ToString()const
{
switch(value)
{
case 0: return "Monday";
case 1: return "Tuesday";
...
}
}
static const int Monday = 0;
static const int Tuesday = 1;
static const int Wednesday = 2;
static const int Thursday = 3;
static const int Friday = 4;
static const int Saturday = 5;
static const int Sunday = 6;
private:
int value;
};
Then you can use syntax like:
Day d = Day::Monday;
cout << d.ToString() << endl;
I think any overhead would be negligible. You could even make
it a template so that the underlying type could be any kind of
integer type. It also seems like it would integrate without
any issues into existing code bases. Any problems with this?

Too much work:). I'll wrap a standard enum in a struct when I
need the scoping (and will use the scoped enums once they become
available), and I've written a program which will parse enums
(in the C++ source code) and generator toEnumType( std::string )
and toString( EnumType ) functions (as well as the overloaded >>
and << operators). Much better to let the machine do the work.
(The program has options for generating various overloaded
operators as well, and checked casts, and instantiation of
std::numeric_limits and an iterator over the enum values---the
latter was trickier than I first imagined, due to the necessity
of supporting one past the end.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,744
Messages
2,569,479
Members
44,899
Latest member
RodneyMcAu

Latest Threads

Top