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);