Test if an enum value is in a range of a derived enum

Andrej Mitrovic andrej.mitrovich at gmail.com
Wed May 2 16:38:31 PDT 2012


import std.stdio;

enum Base
{
    One,
    Two,
    Three,
    Four
}

enum Subset : Base
{
    Two = Base.Two,
    Three = Base.Three
}

void main()
{
    Base base = Base.Four;
    if (cast(Subset)base)
    {
        writeln("yes");
    }
}

This writes "yes" so cast is a blunt tool that doesn't work in this
case. to!() doesn't work either (compile error, maybe I should file
this) .
My first attempt to implement this check was to use .min/.max of each
enum like so:

import std.stdio;

enum Base
{
    One,
    Two,
    Three,
    Four
}

enum Subset : Base
{
    Two = Base.Two,
    Three = Base.Three
}

void isSubset(Base base)
{
    if (base >= Subset.min && base <= Subset.max)
        writeln("yes");
    else
        writeln("no");
}

void main()
{
    Base base1 = Base.Three;
    Base base2 = Base.Four;
    isSubset(base1);  // yes
    isSubset(base2);  // no
}

But this is wrong, because Subset might only define "One" and "Four"
in which case "Two" and "Three" will also pass as a subset even though
they're not defined in Subset.

The alternative is to convert the enum to a string and then to the
Subset enum type via the to!() template:

import std.stdio;
import std.conv;

enum Base
{
    One,
    Two,
    Three,
    Four
}

enum Subset : Base
{
    One = Base.One,
    Four = Base.Four
}

void isSubset(Base base)
{
    try
    {
        to!(Subset)(to!string(base));
        writeln("yes");
    }
    catch (ConvException)
    {
        writeln("no");
    }
}

void main()
{
    Base base1 = Base.One;
    Base base2 = Base.Two;
    isSubset(base1);  // yes
    isSubset(base2);  // no
}

This works but is arguably slow. Personally I'd love it if I could use
the in operator for this, e.g.:

Base base1 = Base.Two;
assert(base1 in Subset);

Anyone know of any other solutions?


More information about the Digitalmars-d-learn mailing list