Created
October 29, 2011 21:26
-
-
Save MartinNowak/1325111 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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