Fwd: Re: Useful applications for boolean increments?
> 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.
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.
> Now all this is to patch the monstrosity that is enum in C. The
> relevance to your question is that, in any reasonable semantics,
> type bool would be an enum{false, true} and not an integer. We
> actually support use of bool instead of an enum in the above
> constructs, but the metaprogramming to do so is painful.
>
> Consequently I would suggest that rather than make bool even more
> of a special case by removing ++, you should instead fix enum and
> make bool an instance thereof.
1) What I don't quite see is: Why is this a fix of enumeration types?
Unless I misunderstand what you are suggesting, this change would only
have the effect do add a concrete enumeration type to the library. I'm
assuming that means that type bool is added as some concrete
enumeration type to the global namespace. Will there also exist a type
bool in namespace std (Actually all library components are within
namespace std, such as std::nullptr_t)?
2) Assuming that I correctly understand you, this would transform type
bool into an otherwise completely normal enumeration type. This would
have the effect that e.g.
int i = 13;
bool b = i;
would no longer compile. Assuming you solve this (somehow) other
examples like
double d = 1e29;
bool b = d;
would now have undefined behaviour, because it falls under 4.9:
"The conversion truncates; that is, the fractional part is discarded.
The behavior is undefined if the truncated value cannot be represented
in the destination type."
It would also mean that now
void test(int* p) {
bool i = p;
}
would no longer compile. Same thing for member pointers. This would
also mean that you could no longer specify that the value of a
condition within a statement (like 'if' or 'while') is type bool,
because when you still do so, other popular idioms like
void test(int* p) {
if (p) { ... }
}
would no longer work (because you cannot implicitly convert a pointer
value to an enum value). Would these be considered as
reinterpret_casts to bool, instead?
Now I'm pretty sure that you don't want to ban all these code
examples, therefore this looks to me as if you would need to define a
lot of extra rules that say: "Well, bool is actually an enum, but
...".
This sounds like a model to me, that initially would introduce several
unresolved problems to the core language. Could you elaborate a bit
more on your proposal to give some directions how to solve these side
effects of such a change?
Thanks && Greetings from Bremen,
Daniel Kr?gler
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 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.
In my day I have been a language lawyer - my name is in the Algol 68
revised report - but I am certainly not familiar with the C or C++
standard to the degree needed to suggest modifications without grave
unintended consequences. However, I'll do my best to respond to your
questions regarding the language and syntax legacy.
K&R C, and BCPL before it, had only fixed integer for a data type, at
most 16k for compiler and source, and a strong aversion to
carpal-inducing Model33 teletype key presses. Everything was an integer
and terse beyond reason.
The present language contains legacy cow flops from that distant day.
Among other holdovers is the use of zero as a null pointer, the elision
of "if (foo == 0)" to "if (foo)", 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. 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. And so on.
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 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.
Over decades the old forms could be deprecated and abandoned. In my
personal opinion the standard blew a gorgeous opportunity to fix enum
once and for all, but instead fell into half measures by adding scoping
and nothing else.
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.
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".
Applied to your examples,
void test(int* p) {
bool i = p;
}
would still compile, with a warning, but
void test(int* p) {
std::boolean i = p;
}
would not, while:
void test(int* p) {
std::boolean i = p == nil;
}
would.
Pity it wasn't done back when "bool" was first added to C as a type.
Ivan
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]