safe assign of int to enum

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

safe assign of int to enum

Oliver.Kowalke-2
Hello,
is a technique available in boost in order to assign an int value to a
enum?

enum E
{
  e1 = 1,
  e2 = 2,
  e3 = 3
};

E e( static_cast< E >( 1) ); // should work

E e( static_cast< E >( 5) ); // should throw exception at runtime

Regards,
Oliver
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Sohail Somani
By defn, static_cast does not provide runtime checks. You should use an
enum class or something. Boost needs scoped enums!

Anyway, I've used this with varying degrees of success but its not
really easy to specialize:

#include <cassert>

struct MyEnum
{
        enum type
        {
                a,b,c,
                min=a,
                max=c
        };
};

template<typename Enum>
typename Enum::type convert_enum(int a)
{
        typedef typename Enum::type type_;
        assert(a >= Enum::min && a <= Enum::max);
        return type_(a);
}

int main()
{
        MyEnum::type b(convert_enum<MyEnum>(0)); // ok
        MyEnum::type a(convert_enum<MyEnum>(5)); // dies
}

> -----Original Message-----
> From: [hidden email]
> [mailto:[hidden email]] On Behalf Of
> [hidden email]
> Sent: Sunday, March 26, 2006 10:42 PM
> To: [hidden email]
> Subject: [Boost-users] safe assign of int to enum
>
> Hello,
> is a technique available in boost in order to assign an int value to a
> enum?
>
> enum E
> {
>   e1 = 1,
>   e2 = 2,
>   e3 = 3
> };
>
> E e( static_cast< E >( 1) ); // should work
>
> E e( static_cast< E >( 5) ); // should throw exception at runtime
>
> Regards,
> Oliver
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Tomas Puverle
> template<typename Enum>
> typename Enum::type convert_enum(int a)
> {
> typedef typename Enum::type type_;
> assert(a >= Enum::min && a <= Enum::max);
> return type_(a);
> }

This won't work for enums where the range is not continuous.

I wrote a library for "smart enums" that allow you to:

1)  Keep a forward and reverse mappings between enums and strings (in fact,
you can use multiple strings for a single enum value ;) This is done in such a
way that you can't fail to update the string table if you add/change an enum
and vice versa.
2)  Compile time and runtime validity checking (depending on the operation).  
So for example trying to convert from a string to an enum will be runtime
checked but trying to assign a constant to a the enum will be compile time
checked.  At the moment I don't have a "intToEnum()" function, which is what
you want but that would be trivial to add (5 lines of code or so).
3)  Enums can be checked for validity (e.g. unitialised enums are not valid),
as well as iterated (even if not a continuous range), strings retrieved, etc.
4)  The enum values are still static compile time constants, so you can use
them in switch statements etc.
5)  There is support for bit manipulation, so you can e.g. unparse a string in
the form of (X|Y|Z) into an integer and vice versa
6)  It's fast!  There is minimal overhead to all these operations.  The most
expensive operation in the library is the conversion from string to enum (a
map lookup)
7)  There is an automatic enum value called "COUNT" which will give you the
value of "last+1".  This is a bit meaningless with bitfields and non-
contiguous ranges and also given that the enum values can be iterated, but is
occasionally useful nonetheless.
8)  I tested it with SunCC and gcc.

Possible improvements I am thinking of:
1)  Serialization (from safest to fastest - store the string or a number).  
This would be trivial.
2)  Different underlying types.  At the moment, the enum defaults to being a
long, which will be an overkill in a lot of situations.  Again, this would be
trivial to add.
3)  Maybe support for LuaBind/Boost.Python enums?
4)  At the moment, the enum will always live inside its own "namespace", so
you have to refer to the values as "MyEnum::ENUM1".  I prefer to encapsulate
enums that way instead of having the values spill into the global namespace
but I could look into supporting that.
5)  I could look into integration with existing enums (e.g. if sharing code
with C)

Would there be interest in such a library?  If so, I will check with our legal
if I can post the code (the fun of working for a corporation!)

Tom





_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Nat Goodspeed
In reply to this post by Oliver.Kowalke-2
> -----Original Message-----
> From: [hidden email] [mailto:boost-users-
> [hidden email]] On Behalf Of Tomas Puverle
> Sent: Monday, March 27, 2006 3:07 PM
> To: [hidden email]
> Subject: Re: [Boost-users] safe assign of int to enum
>
> I wrote a library for "smart enums" that allow you to:
>
> 1)  Keep a forward and reverse mappings between enums and strings (in
> fact,
> you can use multiple strings for a single enum value ;) This is done
in
> such a
> way that you can't fail to update the string table if you add/change
an
> enum
> and vice versa.

[Nat] I have long wished the compiler would support mapping enums
to/from string. If you have a maintainable way to do that, I'm very
interested.
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Sohail Somani
In reply to this post by Oliver.Kowalke-2
> -----Original Message-----
> From: [hidden email]
> [mailto:[hidden email]] On Behalf Of
> Tomas Puverle
> Sent: Monday, March 27, 2006 12:07 PM
> To: [hidden email]
> Subject: Re: [Boost-users] safe assign of int to enum
>
> > template<typename Enum>
> > typename Enum::type convert_enum(int a)
> > {
> > typedef typename Enum::type type_;
> > assert(a >= Enum::min && a <= Enum::max);
> > return type_(a);
> > }
>
> This won't work for enums where the range is not continuous.
>
> I wrote a library for "smart enums" that allow you to:

I am aware of these limitations :) I vote for post!
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Tim Robertson-3
In reply to this post by Tomas Puverle
I've wasted many hours doing most of these things, so I would be
interested in seeing your solution.

At the very least, could you post some information on the approach you
used to keep the forward/reverse mappings updated automatically?  Also,
were you able to do all of this without balooning the size of your
"enums"?  I've never found a way to do that....

-tim

Tomas Puverle wrote:

>>template<typename Enum>
>>typename Enum::type convert_enum(int a)
>>{
>> typedef typename Enum::type type_;
>> assert(a >= Enum::min && a <= Enum::max);
>> return type_(a);
>>}
>
>
> This won't work for enums where the range is not continuous.
>
> I wrote a library for "smart enums" that allow you to:
>
> 1)  Keep a forward and reverse mappings between enums and strings (in fact,
> you can use multiple strings for a single enum value ;) This is done in such a
> way that you can't fail to update the string table if you add/change an enum
> and vice versa.
> 2)  Compile time and runtime validity checking (depending on the operation).  
> So for example trying to convert from a string to an enum will be runtime
> checked but trying to assign a constant to a the enum will be compile time
> checked.  At the moment I don't have a "intToEnum()" function, which is what
> you want but that would be trivial to add (5 lines of code or so).
> 3)  Enums can be checked for validity (e.g. unitialised enums are not valid),
> as well as iterated (even if not a continuous range), strings retrieved, etc.
> 4)  The enum values are still static compile time constants, so you can use
> them in switch statements etc.
> 5)  There is support for bit manipulation, so you can e.g. unparse a string in
> the form of (X|Y|Z) into an integer and vice versa
> 6)  It's fast!  There is minimal overhead to all these operations.  The most
> expensive operation in the library is the conversion from string to enum (a
> map lookup)
> 7)  There is an automatic enum value called "COUNT" which will give you the
> value of "last+1".  This is a bit meaningless with bitfields and non-
> contiguous ranges and also given that the enum values can be iterated, but is
> occasionally useful nonetheless.
> 8)  I tested it with SunCC and gcc.
>
> Possible improvements I am thinking of:
> 1)  Serialization (from safest to fastest - store the string or a number).  
> This would be trivial.
> 2)  Different underlying types.  At the moment, the enum defaults to being a
> long, which will be an overkill in a lot of situations.  Again, this would be
> trivial to add.
> 3)  Maybe support for LuaBind/Boost.Python enums?
> 4)  At the moment, the enum will always live inside its own "namespace", so
> you have to refer to the values as "MyEnum::ENUM1".  I prefer to encapsulate
> enums that way instead of having the values spill into the global namespace
> but I could look into supporting that.
> 5)  I could look into integration with existing enums (e.g. if sharing code
> with C)
>
> Would there be interest in such a library?  If so, I will check with our legal
> if I can post the code (the fun of working for a corporation!)
>
> Tom
>
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Sohail Somani
In reply to this post by Oliver.Kowalke-2
> -----Original Message-----
> From: [hidden email]
> [mailto:[hidden email]] On Behalf Of Tim
> Robertson
> Sent: Monday, March 27, 2006 3:46 PM
> To: [hidden email]
> Subject: Re: [Boost-users] safe assign of int to enum
>
> I've wasted many hours doing most of these things, so I would be
> interested in seeing your solution.
>
> At the very least, could you post some information on the
> approach you
> used to keep the forward/reverse mappings updated
> automatically?  Also,
> were you able to do all of this without balooning the size of your
> "enums"?  I've never found a way to do that....

You make a good point. We should want
sizeof(other_enum)==sizeof(c_enum). Not everyone needs to map between
strings and enumerations
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Tomas Puverle
In reply to this post by Tim Robertson-3
> I've wasted many hours doing most of these things, so I would be
> interested in seeing your solution.

Tim,

Thanks for the interest.  As I said, at this point this is an IP issue and I
want to make sure I do everything the right way (my job depends on it ;)
I will (hopefully) post more details as soon as soon as I hear back from legal.

Tom


_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Tomas Puverle
In reply to this post by Sohail Somani
> You make a good point. We should want
> sizeof(other_enum)==sizeof(c_enum). Not everyone needs to map between
> strings and enumerations

While I can't guarantee that, that is the case most of the time.  Put it this
way - it will be true if your compiler will take a structure with one member
and no virtual functions and make sizeof(structure)==sizeof(member).
I think I will add a feature to allow the programmer to specify the underlying
enum size, too (i.e. int, long, etc.)
As I said, the implementation is both space and time efficient.

Tom





_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: safe assign of int to enum

Tim Robertson-3
FYI:  Some googling tells me that there is current work underway (since  
2002?) on a Boost enum library.  Go here for a tarball of the latest  
candidate:

http://boost-consulting.com/vault/index.php?
action=downloadfile&filename=enum_rev4.6.zip&directory=&PHPSESSID=aae83f
bb6983e99c3a7b00c813f10502&PHPSESSID=aae83fbb6983e99c3a7b00c813f10502

-tim

On Mar 27, 2006, at 5:52 PM, Tomas Puverle wrote:

>> You make a good point. We should want
>> sizeof(other_enum)==sizeof(c_enum). Not everyone needs to map between
>> strings and enumerations
>
> While I can't guarantee that, that is the case most of the time.  Put  
> it this
> way - it will be true if your compiler will take a structure with one  
> member
> and no virtual functions and make sizeof(structure)==sizeof(member).
> I think I will add a feature to allow the programmer to specify the  
> underlying
> enum size, too (i.e. int, long, etc.)
> As I said, the implementation is both space and time efficient.
>
> Tom
>
>
>
>
>
> _______________________________________________
> Boost-users mailing list
> [hidden email]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users