"Reusable" operator overloading for enum?

N

nick

    [...]
Marcel, your solution works perfectly. I like how it
'documents' the enum as being a flag set. I'm using this for
now with a few small additions, but now I'm curious why people
seem generally opposed to macros...

Because they don't obey scope.  In this case, all of the other
solutions have worse problems, so macros are the way to go,

True, but it sounds a little like apples and oranges... preprocessor
directives don't have any concept of scope or anything else in the
code besides other preprocessor stuff. It wouldn't make sense for
macros to obey scope as scope means nothing to them. I guess it would
be nice if you could put a macro inside of a namespace, but I'm not
sure that's realistic?
The safest solution is probably just to use unary + for the
conversion, e.g.:

    MyEnum
    operator|( MyEnum lhs, MyEnum rhs )
    {
        return static_cast< MyEnum >( +lhs | +rhs );
    }

(The unary + operator is an arithmetic operator, so forces the
conversion of the enum into the underlying type, just as -
would.)  If this looks too weird or exotic, there's always
"+ 0" instead.


I have some template metacode somewhere which evaluates the
underlying type, but IIRC, it's a bit hairy.  Most of the time,
you don't need variables of the underlying type, however, and
the unary + trick is sufficient.

That + trick is great, it actually makes a lot of sense and doesn't
seem weird at all. In light of your comments and Marcels', I've
revised the macro again...

#define FLAGS_(T) \
inline static T operator * (bool l, T r) \
{ return static_cast<T>(l*+r); } \
inline static T operator * (T l, bool r) \
{ return static_cast<T>(+l*r); } \
inline static T operator | (T l, T r) \
{ return static_cast<T>(+l|r); } \
inline static T operator & (T l, T r) \
{ return static_cast<T>(+l&r); } \
inline static T operator + (T l, T r) \
{ return l|r; } \
inline static T operator - (T l, T r) \
{ return static_cast<T>(+l-(l&r)); } \
inline static T& operator |= (T& l, T r) \
{ return l = l|r; } \
inline static T& operator &= (T& l, T r) \
{ return l = l&r; } \
inline static T& operator += (T& l, T r) \
{ return l = l+r; } \
inline static T& operator -= (T& l, T r) \
{ return l = l-r; }

....I'm pretty happy with it. Thanks for the help!
 
J

James Kanze

nick wrote:

[...]
I would prefer the use of l&~r, although ~r is not well
defined by the standard so far.

The expression ~r is perfectly well defined by the standard, and
poses no problem. The problem with ~r only comes if you try to
convert the results back into the original enum type (and even
then, only in theory). If both l and r are valid values to
begin with, however, the results of l&~r can be safely converted
back to the original type.
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top