|
Boost : |
Subject: Re: [boost] Enum Conversion
From: Roland Bock (rbock_at_[hidden])
Date: 2012-09-02 17:06:48
On 2012-09-02 22:17, Lorenzo Caminiti wrote:
> On Sun, Sep 2, 2012 at 12:30 PM, Roland Bock <rbock_at_[hidden]> wrote:
>> Hi,
>>
>> In a lot of projects in the company I work for we use Ice middleware
>> which allows to define nice interfaces for services. The IDL also allows
>> to define enums, but I cannot set specific values for the enum items.
>> We also need to store some of these values in databases. We use int to
>> represent the enumerations.
>>
>> Since we might feel the need to add more items to an enum or delete an
>> unused one, we cannot just cast enum to int and vice versa when writing
>> to or reading from the database. We need methods that translate enum to
>> int and back in a stable way that won't change for an individual enum
>> item, even if its position in the enum changes.
>>
>> I found a way to do this, which provides enum<->int and enum<->string.
>> It is used like this:
>>
>> typedef enum
>> {
>> Alpha,
>> Beta,
>> Gamma,
>> Delta,
>> Epsilon
>> } Greek;
>>
>> CREATE_CONVERTER_METHODS(Greek,
>> (Alpha, 5),
>> (Beta, 3),
>> (Gamma, 7),
>> (Delta, 1),
>> (Epsilon, 6));
>>
>> std::cout << GreekToString(IntToGreek(1)) << std::endl;
>> std::cout << GreekToString(IntToGreek(6)) << std::endl;
>> std::cout << GreekToInt(Alpha) << std::endl;
>> std::cout << GreekToString(Alpha) << std::endl;
>> std::cout << IntToGreek(17) << std::endl;
>>
>> ------
>>
>> $ ./a.out
>> Delta
>> Epsilon
>> 5
>> Alpha
>> terminate called after throwing an instance of 'std::invalid_argument'
>> what(): unexpected Greek value
>>
>>
>> My questions are:
>>
>> a) Is this something that might be interesting for others as well? (Or
>> does boost even offer something like that already?)
>> b) I'd really like to be able to write this instead:
>>
>> CREATE_CONVERTER_METHODS(Greek,
>> Alpha = 5,
>> Beta = 3,
>> Gamma = 7,
>> Delta = 1,
>> Epsilon = 6);
>>
>> Obviously, if I could use the preprocessor to translate
>>
>> Alpha = 5 -> (Alpha, 5)
>>
>> I'd be done. But I have no idea how to do that. Any suggestions?
> There's no way you can strip the = symbol with the pp. You can only do:
>
> Alpha = 5 -> (Alpha =, 5)
>
> And that is assuming the number cannot be negative and you don't want
> to use the + sign, otherwise you can only do:
>
> Alpha = -5 -> (Alpha = -, 5)
> Alpha = +5 -> (Alpha = +, 5)
>
> Depending on the code generated by the macro, this *might* be enough:
>
> Alpha = 5 -> (Alpha =, 5)
>
> That is if the name Alpha can always be use in a context where and
> assignment is allowed Alpha =. This includes function parameters with
> defaults, variable declarations, expressions, etc. You could even use
> a type that has an assignment operation from int and returns itself
> when assigned in an expression... For example:
>
> #include <iostream>
>
> struct enum_type
> {
> public: struct identity {};
> public: enum_type ( int const& value ) : value_(value) {}
> public: int operator= ( int const& value ) { return value_ = value; }
> public: int operator= ( identity const& ) { return value_; }
> private: int value_;
> };
>
> int main ( void )
> {
> enum_type Alpha = 5;
> std::cout << (Alpha = enum_type::identity()) << std::endl;
> Alpha = 10;
> std::cout << (Alpha = enum_type::identity()) << std::endl;
> return 0;
> }
>
> Note that Alpha is always used as "Alpha =". You can look at the code
> generated by your macros, see where you use the token Alpha, and
> (creatively) ask yourself if you can replace that with Alpha =
> everywhere maybe via some specially defined operator=. I used tricks
> like these in Boost.Contract to deal with the = trailing the old-of
> variable names.
>
> HTH,
> --Lorenzo
>
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Thanks! That gives me something to think about :-)
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk