can I generate an enum from a typelist?
Vlad Levenfeld
vlevenfeld at gmail.com
Tue Apr 8 01:24:12 PDT 2014
On Tuesday, 8 April 2014 at 07:39:29 UTC, Vlad Levenfeld wrote:
> I'm a beginner to D and I have written this awful code:
>
> struct Layer
> {
> // defs
> alias Types = TypeTuple !(Solid, Gradient, Text, Sprite,
> Plane);
> enum Type
> {
> solid = staticIndexOf !(Solid, Types),
> gradient = staticIndexOf !(Gradient, Types),
> text = staticIndexOf !(Text, Types),
> sprite = staticIndexOf !(Sprite, Types),
> plane = staticIndexOf !(Plane, Types),
> invalid = -1
> }
> struct Solid
> {...}
> struct Gradient
> {...}
> struct Text
> {...}
> struct Sprite
> {...}
> struct Plane
> {...}
> // data
> const Type type;
> union
> {
> Solid solid;
> Gradient gradient;
> Text text;
> Sprite sprite;
> Plane plane;
> }
> // ctor
> @disable this ();
> this (T) (T layer)
> if (not (staticIndexOf !(T, Types) is (Type.invalid)))
> {
> auto type = cast (const Type) staticIndexOf !(T, Types);
> auto type_name = cast (const) to !string (EnumMembers !Type
> [type]);
> mixin ("this."~type_name~"= layer;");
> this.type = type;
> }
> }
>
> So, the layer types are being rewritten 4 times. I anticipate
> hair pulling and teeth grinding when I come back later to add
> more layer types (after I've forgotten the implementation
> details).
>
> Ideally, I'd like to just get the names of all the nested
> structs within the Layer struct and use a template to populate
> both the enum and the union, but I can't use templates to
> change the size of a type (so the union is out) and I have no
> idea how I might lowercase the first letter of each type name
> in the TypeTuple at compile time (there goes the enum).
>
> Is there anything I can do to clean this mess up? Maybe
> there's at least a way to generate an enum off the union using
> std.traits.allMembers or something?
>
> I've got a feeling that my design kind of sucks anyway, so I'm
> open to suggestions to take it in completely different
> direction as well.
After a bit more thought I've managed to eliminate the TypeTuple
and the enum by defining a const TypeInfo member. Also,
std.string.toLower apparently works at compile time. Just when I
thought D couldn't possible get more 'magic'...
Here is my current solution (redundant declarations of Solid...
etc omitted) for critique/completeness/posterity/something:
// data
const TypeInfo type;
union
{
Solid solid;
Gradient gradient;
Text text;
Sprite sprite;
Plane plane;
}
// ctor
@disable this ();
this (T) (T layer)
{
import std.string: toLower;
auto type = cast (const) typeid (T);
auto type_name = cast (const) toLower T.stringof);
mixin ("this."~type_name~"= layer;");
this.type = type;
}
More information about the Digitalmars-d-learn
mailing list