Bug 9206 – std.exception.isValidEnumValue

Status
NEW
Severity
enhancement
Priority
P4
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-12-25T01:54:16Z
Last change time
2024-12-01T16:15:58Z
Assigned to
No Owner
Creator
bearophile_hugs
Moved to GitHub: phobos#9945 →

Comments

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
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/phobos/issues/9945 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB