Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.exception.isValidEnumValue #9945

Open
dlangBugzillaToGithub opened this issue Dec 25, 2012 · 3 comments
Open

std.exception.isValidEnumValue #9945

dlangBugzillaToGithub opened this issue Dec 25, 2012 · 3 comments

Comments

@dlangBugzillaToGithub
Copy link

bearophile_hugs reported this on 2012-12-25T01:54:16Z

Transfered from https://issues.dlang.org/show_bug.cgi?id=9206

CC List

Description

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);
}
//------------------------------------------
@dlangBugzillaToGithub
Copy link
Author

andrej.mitrovich (@AndrejMitrovic) commented on 2013-01-20T13:55:08Z

Is this a duplicate or just related to Issue 8594?

@dlangBugzillaToGithub
Copy link
Author

bearophile_hugs commented on 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.

@dlangBugzillaToGithub
Copy link
Author

andrej.mitrovich (@AndrejMitrovic) commented on 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.

@LightBender LightBender removed the P4 label Dec 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants