Thread overview
Re: an enum inside another enum
Jul 26, 2012
Simen Kjaeraas
Jul 26, 2012
Simen Kjaeraas
Jul 26, 2012
maarten van damme
Jul 26, 2012
Simen Kjaeraas
July 26, 2012
On Thu, 26 Jul 2012 13:40:06 +0200, maarten van damme <maartenvd1994@gmail.com> wrote:

> enum first : string{
>  a="a",
>  b="b"
> }
>
> enum second : string{
>  a=first.a,
>  b=first.b,
>  c="c"
> }
>
> Is there a way to make this cleaner?

string EnumDefAsString(T)() if (is(T == enum)) {
	string result = "";
	foreach (e; __traits(allMembers, T))
		result ~= e ~ " = T." ~ e ~ ",";
	return result;
}

template ExtendEnum(T, string s)
	if (is(T == enum) &&
	is(typeof({mixin("enum a{"~s~"}");})))
{
	mixin(
	"enum ExtendEnum {"
	~ EnumDefAsString!T() ~ s
	~ "}");
}

enum bar
{
	a = 1,
	b = 7,
	c = 19
}

import std.typetuple;

void main() {
//-----------------------
    alias ExtendEnum!(bar, q{ // Usage example here.
        d = 25
    }) bar2;
//-----------------------
    foreach (i, e; __traits(allMembers, bar2)) {
        static assert( e == TypeTuple!("a", "b", "c", "d")[i] );
    }
    assert( bar2.a == bar.a );
    assert( bar2.b == bar.b );
    assert( bar2.c == bar.c );
    assert( bar2.d == 25 );
    static assert(!is(typeof( ExtendEnum!(int, "a"))));
    static assert(!is(typeof( ExtendEnum!(bar, "25"))));
}

-- 
Simen
July 26, 2012
I've also written this implementation of enumerations. It's a bit different from normal D enums, but supports inheritance, guarantees unique values, as is much more conservative in what conversions and operations it allows.

I'm considering adding addition and subtraction of integers as valid operations, but I'm not sure I want to.

Feel free to critique, hack, improve upon and otherwise use and abuse the code.


--
Simen

July 26, 2012
Such a shame that enums do not allow mixins to be made. This
(mixin(EnumInh!First)) would've been an imho way cleaner solution then
declaring your own kind off enum and doing template magic on that.

I still have some problems with Simen's code (the first one, haven't
yet experimented with enumeration.d)
template ExtendEnum(T, string s)
        if (is(T == enum) && is(typeof({mixin("enum a {"~s~"}");}))){
        mixin(
        "enum ExtendEnum {"
        ~ EnumDefAsString!T() ~ s
        ~ "}");
}

The newly generated ExtendEnum will try to convert my old enum with string fields to integer fields. the mixin should generated "ExtendEnum : string" when passing in an enum with type string. Same problem apply's to the second line of this sniped. enum a doesn't have a type yet so it will try to convert everything to ints.


As I seem to run into problems few others have, is my usage of enum's incorrect?
July 26, 2012
On Thu, 26 Jul 2012 18:08:24 +0200, maarten van damme <maartenvd1994@gmail.com> wrote:

> The newly generated ExtendEnum will try to convert my old enum with
> string fields to integer fields. the mixin should generated
> "ExtendEnum : string" when passing in an enum with type string. Same
> problem apply's to the second line of this sniped. enum a doesn't have
> a type yet so it will try to convert everything to ints.
>
>
> As I seem to run into problems few others have, is my usage of enum's incorrect?

I had not considered non-int enums in the first version. There is nothing
wrong with the way you use enums, though I haven't yet found a good reason
to extend them (I just like to :p).

Fixed version below:


import std.traits : OriginalType;

string EnumDefAsString(T)() if (is(T == enum)) {
	string result = "";
	foreach (e; __traits(allMembers, T))
		result ~= e ~ " = T." ~ e ~ ",";
	return result;
}

template ExtendEnum(T, string s)
	if (is(T == enum) &&
	is(typeof({mixin("enum a: OriginalType!T {"~s~"}");})))
{
    mixin(
    "enum ExtendEnum : OriginalType!T {"
    ~ EnumDefAsString!T() ~ s
    ~ "}");
}

enum bar : string {
	a = "a",
	b = "r",
	c = "t",
}

enum baz {
    a = 1,
    b = 2,
    c = 3,
}

unittest {
    alias ExtendEnum!(bar, q{ // Usage example here.
        d = "Text"
    }) bar2;

    foreach (i, e; __traits(allMembers, bar2)) {
        static assert( e == ["a", "b", "c", "d"][i] );
    }
    assert( bar2.a == bar.a );
    assert( bar2.b == bar.b );
    assert( bar2.c == bar.c );
    assert( bar2.d == "Text" );
    static assert(!is(typeof( ExtendEnum!(int, "a"))));
    static assert(!is(typeof( ExtendEnum!(bar, "25"))));
}

unittest {
    alias ExtendEnum!(baz, q{ // Usage example here.
        d = 25
    }) baz2;

    foreach (i, e; __traits(allMembers, baz2)) {
        static assert( e == ["a", "b", "c", "d"][i] );
    }
    assert( baz2.a == baz.a );
    assert( baz2.b == baz.b );
    assert( baz2.c == baz.c );
    assert( baz2.d == 25 );
    static assert(!is(typeof( ExtendEnum!(baz, "25"))));
}

void main() {
}
-- 
Simen