Comment #0 by bearophile_hugs — 2012-12-25T01:54:16Z
Sometimes in a program instances of enumerates values contain a value that's not one of the allowed ones, because of missed initialization ("= void"), data corruption, badly done casts of integral values to enum instance values, and so on.
So I sometimes validate an enum instance in function pre-conditions. Below there is a first implementation of such isValidEnumValue() validating function, meant to be used mostly in pre-conditions. I suggest to add something similar to this to std.exception:
//------------------------------------------
import std.traits: EnumMembers, isIntegral, isSomeChar;
import std.algorithm: canFind;
@property bool isCompleteIntervalEnum(E)()
pure nothrow if (is(E == enum)) {
static if (isIntegral!E || isSomeChar!E) {
return EnumMembers!E.length == (E.max - E.min + 1);
} else {
return false;
}
} unittest { // isCompleteIntervalEnum tests
enum E01 : string { S1="abb", S2="booh", S3="zum" }
static assert(!isCompleteIntervalEnum!E01);
enum E02 : byte { A=-3, S2=4 }
static assert(!isCompleteIntervalEnum!E02);
enum E03: byte { A=0, B=1, C=2 }
static assert(isCompleteIntervalEnum!E03);
enum E04: char { A, B, C }
static assert(isCompleteIntervalEnum!E04);
enum E05: ulong { A=ulong.max, B=ulong.min }
static assert(!isCompleteIntervalEnum!E05);
enum E06: ulong { A=ulong.max, B=ulong.max-1 }
static assert(isCompleteIntervalEnum!E06);
enum E07: char { A='a', B='b', C='c' }
static assert(isCompleteIntervalEnum!E07);
}
bool isValidEnumValue(E)(E e)
pure nothrow if (is(E == enum)) {
static if (isCompleteIntervalEnum!E) {
return e >= E.min && e <= E.max; // Optimization.
} else {
return [EnumMembers!Foo].canFind(e);
}
}
enum Foo { A, B, C=10 }
void bar(Foo f)
in {
assert(isValidEnumValue(f));
} body {
}
void main() {
//Foo f;
Foo f = void;
bar(f);
}
//------------------------------------------
Comment #1 by andrej.mitrovich — 2013-01-20T13:55:08Z
Is this a duplicate or just related to Issue 8594?
Comment #2 by bearophile_hugs — 2013-01-20T14:45:03Z
(In reply to comment #1)
> Is this a duplicate or just related to Issue 8594?
This enhancement request is for a function to be used mostly at run-time, like inside pre-conditions, to validate single enum arguments.
Issue 8597 is meant to be used mostly at compile-time to validate array literals of enums (like strings literals of enum chars). So they are related but they are not the same thing, they aren't a duplicate of each other. (Maybe it's possible to implement part of one using the other, but not fully). So I think they should be kept separated.
Comment #3 by andrej.mitrovich — 2013-01-25T15:53:47Z
(In reply to comment #0)
> @property bool isCompleteIntervalEnum(E)()
> pure nothrow if (is(E == enum)) {
> static if (isIntegral!E || isSomeChar!E) {
> return EnumMembers!E.length == (E.max - E.min + 1);
> } else {
> return false;
> }
> }
That's an interesting optimization.
> bool isValidEnumValue(E)(E e)
> pure nothrow if (is(E == enum)) {
> static if (isCompleteIntervalEnum!E) {
> return e >= E.min && e <= E.max; // Optimization.
> } else {
> return [EnumMembers!Foo].canFind(e);
> }
> }
A mixed-in switch will be slightly faster in the else clause, except in the case of floating-point which can't be used with switches.
Anyway I think it's worth adding.
Comment #4 by robert.schadek — 2024-12-01T16:15:58Z