www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Test if an enum value is in a range of a derived enum

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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?
May 02 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Andrej Mitrovic:

 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) .

Seems worth filing.
 Anyone know of any other solutions?

Write your own function to perform the test, using a liner loop? Bye, bearophile
May 02 2012