Function refract
Return a Function object that captures all the aspects of fun, using the
value of localName to represent the return and parameter types, and the
UDAs. Set the Function's overloadIndex property to index, or to -1 if
it is not specified.
Function refract(alias fun, string localName, int overloadIndex = -1)()
if (is(typeof(fun) == function));
The localName parameter is, in general, *not* the function name. Rather,
it is a compile-time expression that involves only symbols that exist in the
caller's scope, for example a function alias passed as a template
parameter. See
https
//stackoverflow.com/questions/32615733/struct-composition-with-mixin-and-templates/32621854#32621854 for a detailed explanation.
Parameters
| Name | Description |
|---|---|
| fun | a function |
| localName | a string that represents fun in the caller's context |
| overloadIndex | index of fun in its overload set, or -1 |
Example
pure @nogc int answer(lazy string question);
alias F = answer; // typically F is a template argument
static assert(
refract!(F, "F") .mixture ==
"pure @nogc @system %s.ReturnType!(F) answer(lazy %s.Parameters!(F)[0] _0);"
.format(__MODULE__, __MODULE__));
Example
import std .format;
import std .traits : FunctionAttribute;
import bolts .experimental .refraction;
interface GrandTour {
pure int foo() immutable;
@nogc @trusted nothrow ref int foo(
out real, return ref int, lazy int) const;
@safe shared scope void bar(scope Object);
}
class Mock(Interface) : Interface {
static foreach (member; __traits(allMembers, Interface)) {
static foreach (fun; __traits(getOverloads, Interface, member)) {
mixin({
enum Model = refract!(fun, "fun");
if (is(ReturnType!fun == void)) {
return Model .withBody("{}") .mixture;
} else if (Model .attributes & FunctionAttribute .ref_) {
return Model .withBody(q{{
static %s rv;
return rv;
}} .format(Model .returnType)) .mixture;
} else {
return Model .withBody(q{{
return %s.init;
}} .format(Model .returnType)) .mixture;
}
}());
}
}
}
GrandTour mock = new Mock!GrandTour;
real x;
int i, l;
mock .foo(x, i, l++) = 1;
assert(mock .foo(x, i, l++) == 1);
assert(l == 0);