
I've updated the BOOST_ENUM stuff in the file vault: *http://tinyurl.com/cznqu * Currently, there are three flavors of enumerated types available. 1. BOOST_ENUM This type of enum provides the user with a simple way to express an enum. example usage: BOOST_ENUM(boolean, (False) (True) ) This flavor does not allow each element of the enum to be defined. It is assumed that the first element will begin with the value 0 and the last element will be equal to the count of elements - 1. The following methods are available with this type: static const_iterator begin() static const_iterator end() static boost::optional<const T> get(size_t index) static boost::optional<const T> parse(const char* str) const char* str() const bool operator == (const T& rhs) const bool operator != (const T& rhs) const ostream& operator << (ostream& os, const T& rhs) 2. BOOST_ENUM_VALUES This flavor of enum is the same as the basic enum flavor but it allows the user to specify values for each element. example usage: BOOST_ENUM_VALUES(VirtualKey, (Space)(0x20) (Prior)(0x21) (Next)(0x22) (End)(0x23) (Home)(0x24) ) In addition to the methods described above with the basic flavor, these are also available: static boost::optional<const T> make(size_t value) size_t value() const 3. BOOST_BITFIELD A bitfield is much like a BOOST_ENUM_VALUES except that each value is interpreted as a bitmask. This allows many common bitmask operations to be done in a more elegant way; forcing the user to only use bitmasks that are in the domain of the defined bitfield. example usage: BOOST_BITFIELD(MouseKey, (LeftButton)(0x0001) (RightButton)(0x0002) (Shift)(0x0004) (Control)(0x0008) (MiddleButton)(0x0010) ) This type has all of the methods defined for a BOOST_ENUM_VALUES along with these: static T all_mask() std::string str() const void operator |= (const T& rhs) T operator | (const T& rhs) const size_t operator & (const T& rhs) const // TODO: add some more of these like &=, ~, etc. str() for this type returns a string instead of a const char* because it has to generate the string on the fly for each instance. Perhaps there is a more compile-time approach, but I think this would involve lots of tagged type lists and such. Taking the MouseKey as an example, one can do this: MouseKey mkLeft = MouseKey::LeftButton; MouseKey mkShift = MouseKey::Shift; MouseKey mk = mkLeft | mkShift; cout << mk << endl; The output will be: LeftButton | Shift Implementation notes: Instead of needing an 'Invalid' element, I just use Boost.Optional now. Thanks a ton for that suggestion Yuval! Using a switch/case instead of an array for storage of the strings and values of the enum turned out to be pretty straight-forward. With this approach, as was noted earlier, there should be no thread safety issues. I've looked at the disassembly of an optimized example with VC8 and it looks like the compiler just gets rid of all the overhead anyway. I also found that using a switch/case made it possible to be re-used across the many flavors. These types are now instanciable, and I think it is much easier/cleaner to use. Instances of BOOST_ENUM and BOOST_ENUM_VALUES store not the value of the enum element, but the index that it appears in the defining sequence. BOOST_ENUM is actually special because its index always matches its value. Because of this, BOOST_ENUM_VALUES takes a small hit for the make() method because it needs to walk through all of the available values and find one that matches. The tricky thing for the user is that make() will return the first element that matches. So if a user defines A and B to both be equal to 10, and the user calls make(10), it will return A. However if the user defines B before A, make(10) will return B. BOOST_BITFIELD stores the actual raw value so that all of the bitwise operators will be fast and efficient. In a previous attempt to write this flavor, I used a std::set<size_t> of indicies. This is expensive both for the bitwise operators and the storage requirements for each instance of this type. The consequence of storing the raw value is that the str() method has a bit of overhead since it has to mask off each element and check to see if the remaining bits match any values defined in the sequence. It also means that, like BOOST_ENUM_VALUES, the order in which the user defines each bitfield element can change the resulting string representation. As always, any comments are much appreciated. -Frank

Frank Laub wrote:
Currently, there are three flavors of enumerated types available.
1. BOOST_ENUM This type of enum provides the user with a simple way to express an enum.
example usage: BOOST_ENUM(boolean, (False) (True) )
This flavor does not allow each element of the enum to be defined. It is assumed that the first element will begin with the value 0 and the last element will be equal to the count of elements - 1. The following methods are available with this type:
static const_iterator begin() static const_iterator end() static boost::optional<const T> get(size_t index) static boost::optional<const T> parse(const char* str) const char* str() const bool operator == (const T& rhs) const bool operator != (const T& rhs) const ostream& operator << (ostream& os, const T& rhs)
1. What about constructors? 2. What happened to the static 'size' member? 3. The get() and parse() methods can return optional<T> rather than optional<const T>. Since everything here is copied-by-value, the const doesn't add much, IMO. 4. You also need operator< for set/map. 5. If you have parse() and operator<<, then I guess adding operator>> would be logical. 6. People would probably want a value() method as you put in BOOST_ENUM_VALUES, in here also.
2. BOOST_ENUM_VALUES This flavor of enum is the same as the basic enum flavor but it allows the user to specify values for each element.
example usage: BOOST_ENUM_VALUES(VirtualKey, (Space)(0x20) (Prior)(0x21) (Next)(0x22) (End)(0x23) (Home)(0x24) )
In addition to the methods described above with the basic flavor, these are also available:
static boost::optional<const T> make(size_t value) size_t value() const
As far as I know, C++ allows the numeric value of a enum to be negative, so instead of size_t (in both these functions), you need a signed type. I also think there would be some confusion between get() and make(). With BOOST_ENUM, get() is naturally the only choice. So users would be tempted to use get() also with BOOST_ENUM_VALUES. But this is probably not what they are after. With BOOST_ENUM_VALUES, make() is what is most useful, and IMO, get() is mostly useless. So maybe get() should do what make() does today, and the old get() functionality should be names get_by_index() or something similar.
As always, any comments are much appreciated.
All in all, great job! Yuval

static const_iterator begin()
static const_iterator end() static boost::optional<const T> get(size_t index) static boost::optional<const T> parse(const char* str) const char* str() const bool operator == (const T& rhs) const bool operator != (const T& rhs) const ostream& operator << (ostream& os, const T& rhs)
1. What about constructors?
T() T(domain index) // domain is the name of the embedded enum type 2. What happened to the static 'size' member? Forgot to mention it, it's still there. 3. The get() and parse() methods can return optional<T> rather than
optional<const T>. Since everything here is copied-by-value, the const doesn't add much, IMO.
OK, I'll buy that. 4. You also need operator< for set/map. I just added this, thanks for pointing it out. 5. If you have parse() and operator<<, then I guess adding operator>>
would be logical.
Hrm, yes, but it's hard to write a templated operator>>. Currently I'm able to template the whole category of enumeration types by just having an overload for enum_base<T>. In the case of the operator>>, I can't output an enum_base<T>, it needs to be a T. So my question is, how do I write operator>> without making it overly generic? 6. People would probably want a value() method as you put in
BOOST_ENUM_VALUES, in here also.
OK, I got rid of the enum_values_base, and just collapsed it into enum_base. Therefore, there's really no different between a BOOST_ENUM and a BOOST_ENUM_VALUES; only the number of columns in the sequence differs.
static boost::optional<const T> make(size_t value)
size_t value() const
As far as I know, C++ allows the numeric value of a enum to be negative, so instead of size_t (in both these functions), you need a signed type.
OK, in order to support the stringtable version, I now allow the user to specify what the datatype of the value portion should be. This makes the enum_base extermely generic. So now it's: BOOST_ENUM_VALUES(VirtualKey, size_t, (Space)(0x20) ... ) I also think there would be some confusion between get() and make().
With BOOST_ENUM, get() is naturally the only choice. So users would be tempted to use get() also with BOOST_ENUM_VALUES. But this is probably not what they are after. With BOOST_ENUM_VALUES, make() is what is most useful, and IMO, get() is mostly useless. So maybe get() should do what make() does today, and the old get() functionality should be names get_by_index() or something similar.
Agreed, I had trouble coming up with a good name for these methods. I like your suggestion of get_by_index(). So now there is a get() which is an alias for get_by_value(), and a get_by_index(). Latest updates are now uploaded as enum_rev4.1.zip in the file vault. -Frank

Frank Laub wrote:
If you have parse() and operator<<, then I guess adding operator>> would be logical.
Hrm, yes, but it's hard to write a templated operator>>. Currently I'm able to template the whole category of enumeration types by just having an overload for enum_base<T>. In the case of the operator>>, I can't output an enum_base<T>, it needs to be a T. So my question is, how do I write operator>> without making it overly generic?
In one of your previous messages you said that you have a template <typename base> struct safe_enum : base; and the macro: BOOST_ENUM(Boolean, (False) (True) ) is expanded to: class Boolean_base { ... }; typedef safe_enum<Boolean_base> Boolean; If this is still the case, then why shouldn't this template <typename base> istream& operator>>(istream &, safe_enum<base> &) { ... } work?
OK, in order to support the stringtable version, I now allow the user to specify what the datatype of the value portion should be. This makes the enum_base extermely generic. So now it's: BOOST_ENUM_VALUES(VirtualKey, size_t, (Space)(0x20) ... )
Sounds great! Any plans to request a review?

template <typename base> struct safe_enum : base;
Actually, now it's class Boolean : public enum_base<Boolean>. If this is still the case, then why shouldn't this
template <typename base> istream& operator>>(istream &, safe_enum<base> &) { ... }
work?
Yeah, I guess I was worried for no reason. operator >> is now implemented much like you suggest. Any plans to request a review? I am unfamilar with the process, where can I get more information about it? I think that the library is almost ready; the bitfield implementation needs to be finished (all bitwise operators should be implemented). I'd really like to try it in a few real-world applications to make sure it is really usable. Latest rev is 4.2 in the file-vault. -Frank

On 12/15/05, Frank Laub <frank.laub@gmail.com> wrote:
Any plans to request a review?
I am unfamilar with the process, where can I get more information about it? I think that the library is almost ready; the bitfield implementation needs to be finished (all bitwise operators should be implemented). I'd really like to try it in a few real-world applications to make sure it is really usable. http://www.boost.org/more/submission_process.htm
-- Best regards, Zigmar

On 12/16/05, Pavel Antokolsky aka Zigmar <zigmar@gmail.com> wrote:
On 12/15/05, Frank Laub <frank.laub@gmail.com> wrote:
Any plans to request a review?
I am unfamilar with the process, where can I get more information about it? I think that the library is almost ready; the bitfield implementation needs to be finished (all bitwise operators should be implemented). I'd really like to try it in a few real-world applications to make sure it is really usable. http://www.boost.org/more/submission_process.htm
OK, I think the next biggest thing left to do is write all the docs. I'm slowly making progress with this. When it's complete I'll request a formal review. -Frank

On 13/12/05, Frank Laub <frank.laub@gmail.com> wrote:
Implementation notes: Instead of needing an 'Invalid' element, I just use Boost.Optional now. Thanks a ton for that suggestion Yuval!
Is the case of BOOST_BITFIELD, could you not simply use 0 as the "nothing" value, instead of optional? Also, is there that much of a use for being able to set the values for BITFIELD? I think a simple version would be enough in most cases... BOOST_BITFIELD_SIMPLE(MouseKey, (LeftButton) // would get the value 1<<0 (RightButton) // would get the value 1<<1 (Shift) // would get the value 1<<2 (Control) // would get the value 1<<3 ... (MiddleButton) // would get the value 1<<n ) and then you could have none ( with value 0 ) and all ( with value ~0, or (1<<n+1)-1 ) - Scott McMurray P.S. As for that bitfield_iterator, it would have value_type bool and act like an random-access iterator over the bits of the enum :P

I'm just trying out enum rev4.3 with Borland 5.6.4 and it fails to compile. This is because of the 'not-found clause' in the parse method. Eg. for the example BOOST_ENUM(boolean, (False) (True) ) that generates: ... typedef boost::optional<boolean> optional; static optional parse(const char* str) { if(strcmp(str, "False") == 0) return optional(False); if(strcmp(str, "True") == 0) return optional(True); return false; } ... [taken from test/enum.cpp] my compiler complains that it can't convert 'bool' to 'boost::optional<boolean>' on the last return statement, and I would tend to agree with it! If I change the return to be: return optional(); Then it compiles. Is there a particular reason why this compiler complains about the conversion whereas the others are fine with it? Would you consider making this change to support this compiler? Richard

Is there a particular reason why this compiler complains about the
conversion whereas the others are fine with it? Would you consider making this change to support this compiler?
I'm happy to make a change that supports more compilers. Thanks for trying it out on Borland. I'll have an update soon. -Frank

Frank Laub wrote:
Is there a particular reason why this compiler complains about the conversion whereas the others are fine with it? Would you consider making this change to support this compiler?
I'm happy to make a change that supports more compilers. Thanks for trying it out on Borland. I'll have an update soon.
Actually, this is not about supporting more compilers - this about fixing a bug. Putting 'return false' there is a bug, plain and simple, and 'return optional()' is the right thing to do, whether we care about more compilers support or not...

I couldn't see how it was valid on other compilers, but I assumed that it had compiled on at least one compiler before being uploaded. There are similar problems in bitfield.hpp line 111 and 117 and base.hpp lines 61 and 67. I can't get enum.cpp (the test/example program) to compile for two reasons: (i) The form for boost::function is the preferred syntax rather than the portable, could it be changed to portable? test_optional_method becomes: template <typename T, typename A> void test_optional_method( A arg, typename T::optional expected, const char* method_name, boost::function1<typename T::optional, A> method ) (ii) My compiler does not like the use of 'typename' in the body of test_enum and test_bitfield, eg in test_enum test_parse(first.str(), typename T::optional(first)); becomes: test_parse(first.str(), T::optional(first)); I can't say which is the correct syntax or if the version without typename works for other compilers. On Wed, 21 Dec 2005 09:15:57 -0000, Yuval Ronen <ronen_yuval@yahoo.com> wrote:
Frank Laub wrote:
Is there a particular reason why this compiler complains about the conversion whereas the others are fine with it? Would you consider making this change to support this compiler?
I'm happy to make a change that supports more compilers. Thanks for trying it out on Borland. I'll have an update soon.
Actually, this is not about supporting more compilers - this about fixing a bug. Putting 'return false' there is a bug, plain and simple, and 'return optional()' is the right thing to do, whether we care about more compilers support or not...

Richard Jennings wrote:
(ii) My compiler does not like the use of 'typename' in the body of test_enum and test_bitfield, eg in test_enum test_parse(first.str(), typename T::optional(first)); becomes: test_parse(first.str(), T::optional(first)); I can't say which is the correct syntax or if the version without typename works for other compilers.
No, it won't. typename should be replaced by BOOST_DEDUCED_TYPENAME, which expands to typename on compilers that require it, and nothing where they reject it. Sebastian Redl

No, it won't. typename should be replaced by BOOST_DEDUCED_TYPENAME, which expands to typename on compilers that require it, and nothing where they reject it.
Ya know, my first implementation used this macro, however I noticed other boost libs that did not use it, so I mistakenly thought it was deprecated. Silly me :) -Frank

On Thu, 22 Dec 2005 09:30:19 -0000, Frank Laub <frank.laub@gmail.com> wrote:
No, it won't. typename should be replaced by BOOST_DEDUCED_TYPENAME, which expands to typename on compilers that require it, and nothing where they reject it.
Ya know, my first implementation used this macro, however I noticed other boost libs that did not use it, so I mistakenly thought it was deprecated. Silly me :)
I'm just trying rev4.5 and sadly that doesn't work! According to the Boost config library this compiler version (5.6.4) and above support the use of 'typename', hence BOOST_DEDUCED_TYPENAME expands to 'typename' and so enum.cpp fails to compile for me :-( I guess that the compiler does not support it in this special case of temporaries? If you wish to continue to persue this troublesome compiler, you can create the temporary value as a local instead: replace: test_parse(first.str(), BOOST_DEDUCED_TYPENAME T::optional(first)); with: BOOST_DEDUCED_TYPENAME T::optional Temp(first); test_parse(first.str(), Temp); enum.cpp line 448 etc. This works with or without BOOST_DEDUCED_TYPENAME for me. Sadly it's a bit inelegant.

On 12/21/05, Richard Jennings <richard.jennings@teraview.com> wrote:
I couldn't see how it was valid on other compilers, but I assumed that it had compiled on at least one compiler before being uploaded.
Ya, I've been building/testing my stuff with: gcc (GCC) 4.0.3 20051201 (prerelease) (Debian 4.0.2-5) gcc (GCC) 3.4.4 (cygming special) MSVC 8.0: Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86

(i) The form for boost::function is the preferred syntax rather than the portable, could it be changed to portable? test_optional_method becomes: template <typename T, typename A> void test_optional_method( A arg, typename T::optional expected, const char* method_name, boost::function1<typename T::optional, A> method )
Fixed. (ii) My compiler does not like the use of 'typename' in the body of
test_enum and test_bitfield, eg in test_enum test_parse(first.str(), typename T::optional(first)); becomes: test_parse(first.str(), T::optional(first)); I can't say which is the correct syntax or if the version without typename works for other compilers.
Fixed with BOOST_DEDUCED_TYPENAME. I don't have a borland compiler handy, so I'm glad there's someone out there willing to try this out. Thanks! -Frank

Is there a particular reason why this compiler complains about the conversion whereas the others are fine with it? Would you consider making this change to support this compiler?
I'm happy to make a change that supports more compilers. Thanks for
Frank Laub wrote: trying
it out on Borland. I'll have an update soon.
Actually, this is not about supporting more compilers - this about fixing a bug. Putting 'return false' there is a bug, plain and simple, and 'return optional()' is the right thing to do, whether we care about more compilers support or not...
I hadn't realized that this was an improper usage of optional. I returned 'false' because it felt like a 'natural' thing to return as that of a failure. Because the compiler and my tests showed this to work, I figured optional had a special bool constructor or something. I've noticed others use a 'none' type. I suppose the default ctor is the preferred way? Thanks for the heads up. -Frank

Frank Laub wrote:
I hadn't realized that this was an improper usage of optional. I returned 'false' because it felt like a 'natural' thing to return as that of a failure. Because the compiler and my tests showed this to work, I figured optional had a special bool constructor or something. I've noticed others use a 'none' type. I suppose the default ctor is the preferred way?
AFAIK, there's no difference between the default constructor and the 'none' constructor. They both construct the optional in the 'un-initialized' state, and you can use whichever you want. Using any other constructor (copy constructor aside) would try to construct the optional's value_type using the argument to the constructor, and put the optional in an 'initialized' state. Sending 'false' as a constructor argument falls into the second category, which is not what you wanted...
Thanks for the heads up.
My pleasure.

Some more suggestions: - a bitfield member returning number of bits set (count() ?) could be useful. - Move io to a separate header so iostream isn't necessary just to use BOOST_ENUM. - Bitfield io should'n force hex, 0-filled output for missing values. Let the caller decide (or at least restore the stream format flags after). - Maybe the io could use the boolalpha flag to decide if a numeric value or text should be used for output. - The normal separator in a stream is characters where isspace returns true, not "|". - I don't think it is necessary for bitfield operator>> to handle multiple entries. It can be added on top by the caller if necessary. It should allow numeric input though. - Bitfield io should also handle format flags like width, right etc. My suggestion is to let the width apply to each item and not to the entire value (entire output can be handled by using a temporary buffer but not the other way around). Code change is trivial. Just save width on entry and apply it before streaming each value when width>0. e.g. cout << boolalpha << setw(10) << setfill('-') << right << mousekey; outputs: -----Shift ---Control cout << noboolalpha << dec << mousekey; outputs: 12

On 21/12/05, Martin <adrianm@touchdown.se> wrote:
Some more suggestions: - The normal separator in a stream is characters where isspace returns true, not "|".
The problem I see with that is the "MIDDLE|LEFT" should be read as a single enum, while "MIDDLE LEFT" should be read as 2. Using the usual fill character for the separator would make it impossible to have more than one BITFIELD-style enum on one line and prevent operator>> from being able to properly read a BITFIELD-style enum without straying from the usual operation of operator>>. And using the "one line with all the values of the enum" is just using ' ' and '\n' as the separators instead of '|' and ' '. Also, '|' matches the in-code usage of enums -- "MIDDLE|LEFT", once read, has the value MIDDLE|LEFT. - Scott

- a bitfield member returning number of bits set (count() ?) could be useful.
Sure, that's nifty. - Move io to a separate header so iostream isn't necessary just to use
BOOST_ENUM.
OK, reasonable. - Bitfield io should'n force hex, 0-filled output for missing values. Let
the caller decide (or at least restore the stream format flags after). - Maybe the io could use the boolalpha flag to decide if a numeric value or text should be used for output. - The normal separator in a stream is characters where isspace returns true, not "|".
Agreed, the stream operators were just me playing around mostly. I'm glad to hear people with specific requirements for it. Making it flexible/customizable for the end-user sounds like a high priority for these features. - I don't think it is necessary for bitfield operator>> to handle multiple
entries. It can be added on top by the caller if necessary. It should allow numeric input though.
Hmm, I'm really trying to free the user from having to write extra code. Would it really hurt anything if the user could specify the delimiters or could enable/disable this functionality? It obviously isn't written yet, so I could just be lazy and leave it as you suggest. - Bitfield io should also handle format flags like width, right etc. My
suggestion is to let the width apply to each item and not to the entire value (entire output can be handled by using a temporary buffer but not the other way around). Code change is trivial. Just save width on entry and apply it before streaming each value when width>0.
e.g. cout << boolalpha << setw(10) << setfill('-') << right << mousekey; outputs: -----Shift ---Control
cout << noboolalpha << dec << mousekey; outputs: 12
OK, I'll monkey around with these suggestions and see how they turn out. Thanks for the comments! -Frank

- I don't think it is necessary for bitfield operator>> to handle multiple
entries. It can be added on top by the caller if necessary. It should allow numeric input though.
Hmm, I'm really trying to free the user from having to write extra code. Would it really hurt anything if the user could specify the delimiters or could enable/disable this functionality? It obviously isn't written yet, so I could just be lazy and leave it as you suggest.
The problem is that the stream doesn't carry around a separator field. It is hardcoded to use isspace() characters. To allow the user to specify the separator you need to add a custom stream manipulator or a locale facet (facet is preferred since you can then apply it globally but it is much harder to use). If you go for a stream manipulator your library will not be header only anymore since you need to allocate storage for xalloc() I forgot one thing in my last post. Don't forget to add BOOST_WENUM for wchar_t strings. A side note: I once started to write a proposal to add a "int_type" separator field to ios_base but never finished it. It would work like this: cout >> 1 >> separator >> 2 >> setseparator(';') >> separator >> 3; output is: 1 2;3 cin >> setseparator(',') >> string1 >> separator >> int1 parses a comma separated file. The default would be traits::eof which would mean isspace() so existing code would still work. Only change in the standard library (outside ios_base) would be operator>> for strings. Once a separator is in ios_base it would be easy to add streaming of containers, tuples etc and replace the broken complex type streaming.

I'm stuck with a basic problem with BOOST_BITFIELD, again using BCB6 and compiling enum.cpp included with the library. The lines: MouseKey A, B; A |= B; fail to compile with 'bitfield_base<MouseKey>::m_value is not accessible' in operator |= in bitfield.hpp. Not sure what's intended here. It would seem that if the following function is being instantiated: void bitfield_base<MouseKey>::operator |= (const MouseKey& rhs) { m_value |= rhs.m_value; } then m_value is not accessible since it's private to bitfield_base. If rhs were of type bitfield_base then it would work. Changing bitfield_base as follows: void operator |= (const bitfield_base<T>& rhs) { m_value |= rhs.m_value; } works for me.

On 12/21/05, Richard Jennings <richard.jennings@teraview.com> wrote:
I'm stuck with a basic problem with BOOST_BITFIELD, again using BCB6 and compiling enum.cpp included with the library.
The lines: MouseKey A, B; A |= B; fail to compile with 'bitfield_base<MouseKey>::m_value is not accessible' in operator |= in bitfield.hpp.
Not sure what's intended here. It would seem that if the following function is being instantiated: void bitfield_base<MouseKey>::operator |= (const MouseKey& rhs) { m_value |= rhs.m_value; } then m_value is not accessible since it's private to bitfield_base. If rhs were of type bitfield_base then it would work.
Well this is weird. The intent is for the Boost.Operators library to see that it can take a MouseKey on the rhs and thereby generate the binary op for me. Since this method is implemented in bitfield_base, it seems that there would be no problem for it to have access to m_value. Changing bitfield_base as follows:
void operator |= (const bitfield_base<T>& rhs) { m_value |= rhs.m_value; }
If I make the return value be void, the Boost.Operators library goes nuts. I can change the rhs type I suppose, that shouldn't hurt anything. I realize I am returning a derived type, but it should be ok because the derived type doesn't have any memory associated with it; all data is in the base. -Frank

On Thu, 22 Dec 2005 09:28:15 -0000, Frank Laub <frank.laub@gmail.com> wrote: [snip]
Changing bitfield_base as follows:
void operator |= (const bitfield_base<T>& rhs) { m_value |= rhs.m_value; }
If I make the return value be void, the Boost.Operators library goes nuts. I can change the rhs type I suppose, that shouldn't hurt anything. I realize I am returning a derived type, but it should be ok because the derived type doesn't have any memory associated with it; all data is in the base.
-Frank
The return type is void in rev4.3 isn't it? I have not changed the return type, only the parameter type? (At least that was my intent)

On 12/22/05, Richard Jennings <richard.jennings@teraview.com> wrote:
[snip]
The return type is void in rev4.3 isn't it? I have not changed the return
type, only the parameter type? (At least that was my intent)
Oh, I have a rev4.5 now. rev4.4 first started to use the Boost.Operatorlibrary so that I didn't have to write so much redundant operator code. That's when the return type got changed from a void to a T&. In rev4.5, I've also modified the rhs so that it takes a const bitfield_base<T>& as you suggest. -Frank

On Thu, 22 Dec 2005 10:40:35 -0000, Frank Laub <frank.laub@gmail.com> wrote:
Oh, I have a rev4.5 now. rev4.4 first started to use the Boost.Operatorlibrary so that I didn't have to write so much redundant operator code. That's when the return type got changed from a void to a T&. In rev4.5, I've also modified the rhs so that it takes a const bitfield_base<T>& as you suggest.
I'll download rev4.5 from the vault and give that a go.

On 12/13/2005 12:37 AM, Frank Laub wrote:
I've updated the BOOST_ENUM stuff in the file vault: *http://tinyurl.com/cznqu [snip]
As always, any comments are much appreciated. Hi, Frank,
I've been using code in the vault/Template Metaprogramming/range_all.zip which is related in that it defines a specialization on enumerations that defines the enumeration size and enables use in template metaprogramming. It would be nice if your code could merge with that code to provide all their capabilities. Of course I don't know if the mpl folks would be willing to accept that as part of their library, but you might give it a try. -best regards, Larry

I'm getting a complaint of an ambiguity when I use BOOST_ENUM_VALUES with std::size_t as the type. eg: BOOST_ENM_VALUES(MyTypeName, std::size_t, (fred)(0) (jane)(1) ) The error is: E2015 Ambiguity between 'boost::optional<unsigned int>::optional(int boost::detail::none_helper::* const &)' and 'boost::optional<unsigned int>::optional(const unsigned int &)' Which is in the static method 'values' for the case where the index is zero. The line is: return optional_value(0); This does not happen if I use 'int', but does also happen with 'unsigned int'. A guess is that the compiler thinks that the zero might be null pointer? A possible solution is to do a cast: return optional_value(static_cast<value_type>(0)); This only happens for the zero value, other values are fine.

On 12/22/05, Richard Jennings <richard.jennings@teraview.com> wrote:
[snip] A possible solution is to do a cast: return optional_value(static_cast<value_type>(0));
This only happens for the zero value, other values are fine.
Can you verify that this is the fix for your compiler? I can't get this to repro with the ones I have. If it does work, I'll make sure the latest rev has this fix in it. -Frank

On Thu, 22 Dec 2005 10:50:03 -0000, Frank Laub <frank.laub@gmail.com> wrote:
On 12/22/05, Richard Jennings <richard.jennings@teraview.com> wrote:
[snip] A possible solution is to do a cast: return optional_value(static_cast<value_type>(0));
This only happens for the zero value, other values are fine.
Can you verify that this is the fix for your compiler? I can't get this to repro with the ones I have. If it does work, I'll make sure the latest rev has this fix in it.
This fixes it for my compiler on rev4.3. It's only needed for the zero value case, not for other values.

Here's a request for an extension to ENUM_VALUES for you to consider. I need to use BOOST_ENUM_VALUES with type std::size_t so I can use the method 'value' and use the result as an index to a vector. I would also like to have an end-user readable description for the enumeration value. Currently I hold this in a separate class that maps enumeration values to descriptions. From what I understand, the enumeration tags have to be C++ names so no spaces are allowed whereas end-users don't usually like CamelCase (or whatever) unspaced C++ names. Here's an example: BOOST_ENUM_VALUES_DESCRIPTIONS(BlockType_t, std::size_t, (SampleIfg)(0)("Sample Interferogram") (SampleSpec)(1)("Sample Spectrum") (SamplePhase)(2)("Sample Phase") (RefIfg)(3)("Reference Interferogram")) And then a method something like: const char* description() const; Would anyone else find this useful?

On 12/22/05, Richard Jennings <richard.jennings@teraview.com> wrote:
Here's a request for an extension to ENUM_VALUES for you to consider. [snip] And then a method something like: const char* description() const;
Would anyone else find this useful?
This is very similar to my very first cut at this that is used at my office. I called this 3rd field a 'comment', but description is a nice name too. I've designed the macros so that it is easy to add a 3rd column. If there really are some fans of this flavor, I'd be happy to add it. -Frank

One alternative is to do this instead: BOOST_ENUM_VALUES(BlockType_t, const char*, (SampleIfg)("Sample Interferogram") (SampleSpec)("Sample Spectrum") (SamplePhase)("Sample Phase") (RefIfg)("Reference Interferogram") ) One principle idea of the Boost.Enum library is to hide the fact that integers are really doing the dirty work. I suppose in this case we could expose a 'raw' or 'native' method that would return the index number of the enumeration element. This could then be used for your vector index. Would this work for you? -Frank

On Thu, 22 Dec 2005 11:04:57 -0000, Frank Laub <frank.laub@gmail.com> wrote:
One alternative is to do this instead:
BOOST_ENUM_VALUES(BlockType_t, const char*, (SampleIfg)("Sample Interferogram") (SampleSpec)("Sample Spectrum") (SamplePhase)("Sample Phase") (RefIfg)("Reference Interferogram") )
One principle idea of the Boost.Enum library is to hide the fact that integers are really doing the dirty work. I suppose in this case we could expose a 'raw' or 'native' method that would return the index number of the enumeration element. This could then be used for your vector index. Would this work for you?
Yes that would work for me. I took it that the spirit of BOOST_ENUM was indeed to hide the basic type and that you should use BOOST_ENUM_VALUES if you wanted to be sure of the value of each enumeration. There's always a 'but', so mine is that using BOOST_ENUM_VALUES as you suggest requires that the enumeration values start with zero. I think that's most cases.

Hi, May be I've missed some messages of the thread, see message here after, but is there any method that would return the index of the enumeration element when using BOOST_ENUM_VALUES. Or if not, if there any convenient way to be able to do that: BOOST_ENUM_VALUES(ErrorType, std::string, (Warning)("Warning...") (BadArg)("Bad argument...") (Fatal)("Fatal error...") void f(ErrorType e) { switch(e) { case ErrorType::Warning: break; case ErrorType::BadArg: break; case ErrorType::Fatal: break; } } I'm using BOOST_ENUM rev 4.5 Thanks in advance. Best regards, Marc Viala mailto:mviala@acticm.com -----Message d'origine----- De : boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] De la part de Richard Jennings Envoyé : jeudi 22 décembre 2005 15:31 À : boost@lists.boost.org Objet : Re: [boost] BOSOT_ENUM proposal rev 4, ENUM_VALUES extension? On Thu, 22 Dec 2005 11:04:57 -0000, Frank Laub <frank.laub@gmail.com> wrote:
One alternative is to do this instead:
BOOST_ENUM_VALUES(BlockType_t, const char*, (SampleIfg)("Sample Interferogram") (SampleSpec)("Sample Spectrum") (SamplePhase)("Sample Phase") (RefIfg)("Reference Interferogram") )
One principle idea of the Boost.Enum library is to hide the fact that integers are really doing the dirty work. I suppose in this case we could expose a 'raw' or 'native' method that would return the index number of the enumeration element. This could then be used for your vector index. Would this work for you?
Yes that would work for me. I took it that the spirit of BOOST_ENUM was indeed to hide the basic type and that you should use BOOST_ENUM_VALUES if you wanted to be sure of the value of each enumeration. There's always a 'but', so mine is that using BOOST_ENUM_VALUES as you suggest requires that the enumeration values start with zero. I think that's most cases. _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 1/15/06, Marc VIALA <mviala@acticm.com> wrote:
Hi,
May be I've missed some messages of the thread, see message here after, but is there any method that would return the index of the enumeration element when using BOOST_ENUM_VALUES.
It was discussed and I agreed to add a method like this but I didn't around to it until recently. The new method is called index(). With it you can do a switch. I'm using BOOST_ENUM rev 4.5 I just uploaded a new version 4.6 to the vault. Thanks in advance.
You're welcome and thanks for your input.
-Frank

Thanks for your reply and your evolution. Great job... A+ Marc Viala mailto:mviala@acticm.com -----Message d'origine----- De : boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] De la part de Frank Laub Envoyé : mardi 17 janvier 2006 18:52 À : boost@lists.boost.org Objet : Re: [boost] BOOST_ENUM proposal rev 4, ENUM_VALUES extension? On 1/15/06, Marc VIALA <mviala@acticm.com> wrote:
Hi,
May be I've missed some messages of the thread, see message here after, but is there any method that would return the index of the enumeration element when using BOOST_ENUM_VALUES.
It was discussed and I agreed to add a method like this but I didn't around to it until recently. The new method is called index(). With it you can do a switch. I'm using BOOST_ENUM rev 4.5 I just uploaded a new version 4.6 to the vault. Thanks in advance.
You're welcome and thanks for your input.
-Frank _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Richard Jennings wrote:
Here's a request for an extension to ENUM_VALUES for you to consider.
Here's an example: BOOST_ENUM_VALUES_DESCRIPTIONS(BlockType_t, std::size_t, (SampleIfg)(0)("Sample Interferogram") (SampleSpec)(1)("Sample Spectrum") (SamplePhase)(2)("Sample Phase") (RefIfg)(3)("Reference Interferogram"))
How about: struct BlockData { BlockData(std::sizt_t a_index, const char *a_description) : index(a_index), description(a_description) { } std::sizt_t index; const char *description; }; BOOST_ENUM_VALUES(BlockType_t, BlockData, (SampleIfg)(BlockData(0, "Sample Interferogram")) (SampleSpec)(BlockData(1, "Sample Spectrum")) ) or even better for my taste: BOOST_ENUM_VALUES(BlockType_t, BlockData, (SampleIfg)({ 0, "Sample Interferogram" }) (SampleSpec)({ 1, "Sample Spectrum" }) ) and then you don't even need to constructor of BlockData. I'm not sure if this compiles, but I hope it does. If it doesn't, can you make it work, Frank? If it does, then I guess it's quite nice for you, Richard, isn't it?

A final suggestion from me: when I run the test/example program enum.cpp I'm pretty sure it completes successfully however it does print out the somewhat worrying words "Error" and "failed" more than once. "Error" is one of the enumeration values while "failed" seems to indicate that the enumerated value requested was out of range, as expected. I suggest that, to avoid confusion, you consider changing these terms, perhaps "failed" becomes "no value" or "out of range" or "invalid value" or something. I'm leaving this company today so I won't be able to try the library on Borland any more. I wish you well with the library and hope that it's accepted, I think it's a valuable addition.
participants (9)
-
Frank Laub
-
Larry Evans
-
Marc VIALA
-
Martin
-
me22
-
Pavel Antokolsky aka Zigmar
-
Richard Jennings
-
Sebastian Redl
-
Yuval Ronen