Thread overview
[Issue 9206] New: std.exception.isValidEnumValue
Jan 20, 2013
Andrej Mitrovic
Jan 25, 2013
Andrej Mitrovic
December 25, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=9206

           Summary: std.exception.isValidEnumValue
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: Phobos
        AssignedTo: nobody@puremagic.com
        ReportedBy: bearophile_hugs@eml.cc


--- Comment #0 from bearophile_hugs@eml.cc 2012-12-25 01:54:16 PST ---
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);
}
//------------------------------------------

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9206


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-01-20 13:55:08 PST ---
Is this a duplicate or just related to Issue 8594?

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 20, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9206



--- Comment #2 from bearophile_hugs@eml.cc 2013-01-20 14:45:03 PST ---
(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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 25, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=9206



--- Comment #3 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-01-25 15:53:47 PST ---
(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.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------