Skip to content

Instantly share code, notes, and snippets.

@MartinNowak
Created October 29, 2011 21:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MartinNowak/1325111 to your computer and use it in GitHub Desktop.
Save MartinNowak/1325111 to your computer and use it in GitHub Desktop.
import std.random, std.traits, std.typecons, std.typetuple;
struct Builder(UserGens...)
{
Tuple!TS genTuple(TS...)()
{
Tuple!TS tup;
foreach(i, T; TS)
tup[i] = gen!T();
return tup;
}
T gen(T)()
{
// pull out the return values of the user defined generators
alias staticMap!(ReturnType, UserGens) UserTypes;
// search user generator for T
enum idx = staticIndexOf!(T, UserTypes);
// match => use it
static if (idx != -1)
{
// construct a random parameter tuple for the generator
auto tup = genTuple!(ParameterTypeTuple!(UserGens[idx]))();
return UserGens[idx](tup.tupleof);
}
// no match => see if we have a default generator
else static if (is(typeof(genImpl!T()) == T))
{
return genImpl!T();
}
else
{
static assert(0, "Don't know how to construct a '"~T.stringof~"'.");
}
}
// some default generators
T genImpl(T)() if (isNumeric!T)
{
return uniform(T.min, T.max);
}
T genImpl(T)() if (isSomeChar!T)
{
return cast(T)uniform(0, 128);
}
T genImpl(T)() if (isArray!T)
{
alias typeof(T.init[0]) Element;
T res;
size_t length = uniform(0, 50);
while (length--)
res ~= gen!Element();
return res;
}
}
// use the random parameter to select one out of four strings
static string genString(uint rnd)
{
switch (rnd % 4)
{
case 0: return "Zero";
case 1: return "One";
case 2: return "Two";
case 3: return "Four";
default: assert(0);
}
}
struct Foo
{
int v;
}
Foo genFoo(int v)
{
return Foo(v);
}
import std.stdio;
void main()
{
Builder!() builder;
writeln(builder.gen!int());
writeln(builder.gen!float());
writeln(builder.gen!(ubyte[])());
writeln(builder.gen!string());
// Use a custom generator for strings
Builder!genString builder2;
writeln(builder2.gen!int());
writeln(builder2.gen!float());
writeln(builder2.gen!(ubyte[])());
writeln(builder2.gen!string());
// writeln(builder2.gen!Foo()); builder2 doesn't know how to construct Foos
Builder!genFoo builder3;
writeln(builder3.gen!Foo());
writeln(builder3.gen!(Foo[])());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment