Issue 9206 - std.exception.isValidEnumValue
Summary: std.exception.isValidEnumValue
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-12-25 01:54 UTC by bearophile_hugs
Modified: 2024-12-01 16:15 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description bearophile_hugs 2012-12-25 01:54:16 UTC
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 Andrej Mitrovic 2013-01-20 13:55:08 UTC
Is this a duplicate or just related to Issue 8594?
Comment 2 bearophile_hugs 2013-01-20 14:45:03 UTC
(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 Andrej Mitrovic 2013-01-25 15:53:47 UTC
(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 dlangBugzillaToGithub 2024-12-01 16:15:58 UTC
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