Re: Fwd: Re: Useful applications for boolean increments?
[I apologize for the late response, but I had some severe problems with
the configuration of my news group reader]
On 2012-10-25 20:31, Ivan Godard wrote:
> I frequently use increment over an enumeration, typically when
> iterating over an array whose index set is an enum. This construct
> is not native to C/C++, but with type traits that give lower/upper
> bounds for enum types and a little meta-programming you can write:
> enum E(f, g, h);
> array<int, E> a, b;
> forEach(x, thru<E>()) {
> a[x] = 17;
> b[x + 1] = 23;
> }
> The metaprogramming ensures that a[5] is illegal. ++ and -- are
> defined as the successor and predecessor operations in the natural
> way, as are E ?? integral and E - E (but of course not E + E) in the
> obvious way. That is, the set of arithmetic operations are the
> same as for pointers.
I agree that this looks like a useful tool. Am I correctly
understanding that this is a view of an enumeration type's range of
valid values (specified by the extreme values b_min and b_max in the
standard)?
Strictly speaking it is defined by the lwb and upb values supplied to
the macro that sets up the traits for the enumeration, and could be any
value coerceable to a constexpr of the enum. In practice they are always
the extrema of the declared values of the enum's list. Neither I nor a
Google search are familiar with std::b_min/max.
The symbols b_min and b_max are defined in 7.2 [dcl.enum] (I'm using
underscore _ to indicate a subscript):
"for an enumeration where e_min is the smallest enumerator and e_max is
the largest, the values of the enumeration are the values in the range
b_min to b_max, defined as follows: Let K be 1 for a two???s complement
representation and 0 for a one???s complement or sign-magnitude
representation. b_max is the smallest value greater than or equal to
max(|e_min| ??? K, |e_max|) and equal to (2^M) ??? 1, where M is a
non-negative integer. b_min is zero if e_min is non-negative and ???(b_max
+ K) otherwise. The size of the smallest bit-field large enough to hold
all the values of the enumeration type is max(M, 1) if b_min is
zero and M + 1 otherwise. It is possible to define an enumeration that
has values not defined by any of its enumerators. If the enumerator-list
is empty, the values of the enumeration are as if the enumeration had a
single enumerator with value 0."
It would be very nice if these extrema and some of the other information
well known to the compiler but hidden by the language were exposed to
the user, instead of requiring manual maintenance of traits. The most
badly needed IMO is an array of strings containing the printnames of the
enumerates.
I agree that deducing this information via some "reflection" mechanism
would be useful.
There are two issues being confused here. My concern is functionality or
lack thereof. The second is the legacy of C and its lack of
functionality that would treat an enum as more than the collection of
#defines that was all C had at the beginning.
I'm not sure that C++ will really change the good old C enums more than
necessary, since you can use enum classes in C++11. For these enums the
value-range is *exactly* identical to the value-range of the underlying
type of the enum (Which again can be queried via the trait
std::underlying_type).
Note that *if* you are interested in traversing over the enumerators of
an enum, you seem to make special assumptions, because there is no
guarantee that they are ascending, or unique values in general. I
emphasis this, because I think that your iteration facility depends on
that guarantees. As you say above, the programmer typically defines them
as the first and last values, but I think there exists more than one
reasonable choice here. But you know that.
I have strong opinions regarding the functionality, and our code goes a
long way toward making the enum concept useful via some tortuous
metaprograming and traits classes. I can and have offered the improved
functionality to the language.
The next round of the language evolution has just started, so everything
that didn't came in yet has a new chance now, when someone argues in
favour for it. If you have an existing proposal paper in your mind,
could you please send the corresponding issue number or a link to it?
The present language contains legacy cow flops from that distant day.
Among other holdovers is the use of zero as a null pointer,
Agreed, and the core working group seems to be willing to reduce that
usage, see e.g.
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903
With nullptr existing, only limited reasons exist for this idiom.
the elision
of "if (foo == 0)"
Agreed.
to "if (foo)",
I strongly disagree in regarding to the "if (foo)" idiom. There is no
evidence that anyone is willing to deprecate or to remove this from the
language. This idiom is very popular and well understood.
and the coercion rules for bool and
enums.
All of these idioms are deprecated in our code. They are removed in code
reviews and in some cases by tools or metaprogramming. Heightened
readability results: if you see "if (foo)", then you know that foo is a
boolean variable, not a pointer.
This may be true for your working group but I think that this strict
interpretation is note very widely accepted.
If you see "switch(foo)" you can be
confident that all the case labels are actually enumerates of the class
of foo and not some other enumeration or some macroed integer.
switch is different and does not perform "contextual conversion to bool"
as if or while do.
Recently the standard took some halting steps toward cleaning up the
zero-as-null issue, and introduced enum class so at least spurious name
collisions among enumerates could be avoided. Kudos. Unfortunately, we
now have yet more half measures that merely complicate compiler and mind
without being functional.
I'm not sure whether I correctly understand this: Are you criticizing
that old enums are still supported? If you prefer enum classes, why not
using them and not bothering the old ones?
I do not believe that it would be possible or desirable to eliminate the
legacy idioms you list, breaking billions of lines of code. I feel that
the only pragmatically possible solution is to introduce a new properly
designed and functionally complete structure in parallel with the legacy
facilities, in the way that enum class (scoped enums) were introduced.
So you suggest to introduce a second bool type? But given you statement
above wouldn't that have the exact same effect as you describe above as:
"Unfortunately, we now have yet more half measures that merely
complicate compiler and mind without being functional."
Enum class is not so widespread today that it cannot be amended and
extended still, and it should be. It should be merged with the class
concept: constructors, inheritance and all. The syntactic sugar of a
convenient notation for creation of a set of unique value should be
retained and extended to classes in general. And the standard should
expose metadata for reflexive programming: there is no excuse for not
making print names of enumerates available, nor for not making the types
and names of set of data members available. The machinery is there in
the language to do so, and forcing the users to do it by hand is
unfriendly in the extreme.
These are a lot of things and presumably there are some different issues
involved.
Returning to bool, it might be possible to mangle the standard to make
bool a proper enumeration while leaving the legacy cow pats, but I doubt
it. Hence I suggest adding "enum class boolean" to the language with
either a conversion function or an explicit constructor for cow flop
compatibility. Making "if" also accept the new enum class should be easy
in the standard. With enum class fixed, there should not be any added
work in the compilers to handle enum boolean because it's just another
enum class and need not be special cased except for "if".
OK, this seems different as I first understood, it does look more like a
new boolean type instead of a "enforce-it-into-some-enum" bool type. I'm
not sure why these type families need to be connected. Your problems
could be solved by introducing a new type "bool class" with the
properties you describe without any relation to enums.
I have no idea how much support your ideas get, but I think it really
needs a complete proposal to better understand the consequences of what
you are suggesting.
Thanks for your response,
- Daniel
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]