Skip to content

Instantly share code, notes, and snippets.

@Yoplitein
Created September 5, 2022 22:32
Show Gist options
  • Save Yoplitein/01f55f5121773f8d936be44950fa6c63 to your computer and use it in GitHub Desktop.
Save Yoplitein/01f55f5121773f8d936be44950fa6c63 to your computer and use it in GitHub Desktop.
Generic implementation of the builder pattern for any struct/class (though only for public fields)
auto builder(T)(T inst = T.init)
{
enum isClass = is(T == class);
static assert(is(T == struct) || isClass, "builder!T can only build structs and classes");
static if(isClass)
if(inst is null) inst = new T;
static struct Builder
{
private T inst;
T build()
{
return inst;
}
typeof(this) opDispatch(string prop)(typeof(mixin("inst.", prop)) value)
{
mixin("inst.", prop, " = value;");
return this;
}
}
return Builder(inst);
}
unittest
{
static struct Foo
{
int x;
string y;
}
auto x = builder!Foo
.x(10)
.y("foo")
.build
;
assert(x.x == 10);
assert(x.y == "foo");
static class Bar
{
int x;
string y;
}
auto y = builder!Bar
.x(20)
.y("bar")
.build
;
assert(y.x == 20);
assert(y.y == "bar");
static assert(!__traits(compiles, { auto b = builder!int; }));
static assert(!__traits(compiles, { auto b = builder!Foo; b.x(""); }));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment