Re: max enum value +1
In article <2b859b0e-39bb-4e3e-a680-61efa3311642@googlegroups.com>,
fmatthew5876@googlemail.com (fmatthew5876) wrote:
The count of the number of enum elements is always used in an
integral context (static array sizes are most common, and for loops
over all of the enum values efficiently).
Not in my experience. Are you writing code like:
for (int i = 0; i <= kNumColors; ++i)
use(static_cast<Color>(i));
I much prefer writing:
for (Color i = kBegin; i != kEnd; ++i)
use(i);
where the variable has the type of the enum and there are no naked
casts, even if it means writing:
enum Color {
kCyan, kMagenta, kYellow, kBlack,
kEnd, kBegin = 0
};
inline Color operator++(Color &c) {
assert(c != kEnd);
return c = static_cast<Color>(c+1);
}
Note that using:
enum Color {
kCyan, kMagenta, kYellow, kBlack,
};
constexpr Color kBegin = kCyan;
constexpr int kEnd = kBlack + 1;
Color operator++(Color &c);
for (Color c = kBegin; c != kEnd; ++c)
use(c);
may appear to work, but isn't portable because the compiler is allowed
to store the enum in two bits and kBlack + 1 won't fit in that range.
min(kNumColors, 2), fails to compile because the arguments are of
different type.
Again, I'd never write something like that. Where does the literal 2
come from? Shouldn't it be kGreen? Generally when I am dealing with
enums, my values are of the enum type. They implicitly convert to int
where necessary. For conversions in the other direction, an explicit
cast is probably appropriate.
2) Explicitly count each of the values
enum Color {
kRed = 0,
kBlue = 1,
kGreen = 2
};
constexpr int kNumColors = 3;
This is more work but bugs in the count are easy to spot.
I don't think bugs in the count are easy to spot. Not when the number
of values is large. Having to check that 20 or 30 numbers are in
consecutive order with no gaps makes my eyes glaze over. Also, this
approach isn't very friendly to version control systems. You will
tend to get spurious differences, and merging concurrent edits by
different authors will be more error-prone.
In cases where I don't want the one-past-the-end value to be part of
the enum, I have used:
enum Color {
kRed, kBlue, kGreen,
kLast = kGreen
};
You can add:
constexpr int kNumColors = kLast + 1;
if you want, but I don't bother. Either way, this lets the computer
do the counting, and there's less chance someone will add a value and
forget to update kLast because they are so close together. It's also
easy to check by eye that that hasn't happened.
It would be great if there was just some way to get the max count +1
of any enum.
The notion of "max count" isn't really part of standard enums. It does
have the notion of the enum's range, which comes from the number of
bits needed to store the named enum values. It is allowing for bit
operations like:
Color c = static_cast<Color>(kBlue | kGreen);
which yields a valid value for c, albeit one that is larger than any
named value.
Also note that if our enum is a kind of typed int:
enum { first = 0, last = UINT_MAX };
then max count + 1 will have overflow issues.
-- Dave Harris, Nottingham, UK.
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]