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