apply

Applies the sequence of arguments args to the function or template fun either as function or template arguments, at compile-time or at run-time (if CTFE is not possible).

apply is most likely to be found used as a building block in higher-order templates and AliasSeq algorithms like staticMap which need to call or instantiate (as appropriate) functions or templates, passed as parameters.

Members

Aliases

apply
alias apply = Alias!(func(args))
Undocumented in source.
apply
alias apply = func!args
Undocumented in source.
apply
alias apply = Alias!(func!args)
Undocumented in source.

Properties

apply
auto ref apply [@property getter]
Undocumented in source. Be warned that the author may not have intended to support it.

Parameters

args

template / function arguments to apply to fun

Return Value

An alias to fun(args) or fun!(args)

Examples

apply can call regular functions with arguments known either at compile-time, or run-time:

int add(int a, int b) { return a + b; }
enum int a = 2, b = 3;
enum int sum = apply!(add, a, b);
static assert(sum == 5);

int x = 2, y = 5;
int z = apply!((a, b) => a + b, x, y);
assert(z == 7);

// TODO: Show higher-order template example

// When `apply` is used to call functions it returns the result
// by reference (when possible):
static struct S { int x; }
static ref int getX(ref S s) { return s.x; }
static int inc(ref int x) { return ++x; }
auto s = S(41);
int theAnswer = apply!(inc, apply!(getX, s));
assert (theAnswer == 42);
assert (s.x == 42);

apply can also instantiate function templates with compile-time parameters and alias or call them:

int mul(int a, int b)() { return a * b; }

enum product = apply!(mul, 2, 7);
static assert (product == 14);

static int counter = 0;
int offset(int x) { return 10 * ++counter + x; }
alias offset7 = apply!(offset, 7);

assert(offset7()         == 17);
assert(apply!(offset, 7) == 27);
assert(offset7()         == 37);

apply can instnatiate manifest constant (a.k.a. enum) templates:

enum ulong square(uint x) = x * x;
enum result = apply!(square, 3);
static assert(result == 9);

Two or more apply instances can be chained to provide the template and later the run-time arguments of a function template:

static T[] transform(alias fun, T)(T[] arr)
{
    foreach (ref e; arr)
        e = fun(e);
    return arr;
}

alias result = apply!(
    apply!(transform, x => x * x, int),
    [2, 3, 4, 5]);

static assert (result == [4, 9, 16, 25]);

apply can instnatiate alias templates

alias ArrayOf(T) = T[];
alias ArrayType = apply!(ArrayOf, int);
static assert (is(ArrayType == int[]));

import std.traits : CommonType;
alias Types = AliasSeq!(byte, short, int, long);
static assert (is(apply!(CommonType, Types) == long));

apply can instnatiate higher-order templates that yield alias sequences:

1 import std.meta : staticMap;
2 
3 alias ArrayOf(T) = T[];
4 alias Types = AliasSeq!(byte, short, int, long);
5 alias ArrayTypes = apply!(staticMap, ArrayOf, Types);
6 static assert (is(ArrayTypes == AliasSeq!(byte[], short[], int[], long[])));
7 
8 template Overloads(T, string member)
9 {
10     alias Overloads = AliasSeq!(__traits(getOverloads, T, member));
11 }
12 
13 struct S
14 {
15     static int use(int x) { return x + 1; }
16     static bool use(char c) { return c >= '0' && c <= '9'; }
17     static char use(string s) { return s[0]; }
18 }
19 
20 static assert(apply!(Overloads, S, "use").length == 3);
21 
22 alias atIndex(size_t idx, List...) = Alias!(List[idx]);
23 
24 static assert(
25     apply!(  // 3) call the function with the argument `10`
26         apply!(  // 2) get the first element (with type `int use(int x)`)
27             atIndex,
28             0,
29             apply!(Overloads, S, "use") // 1) get the `use` overload set
30         ),
31         10
32     ) == 11);
33 
34 static assert(
35     apply!(apply!(atIndex, 1, apply!(Overloads, S, "use")), '3') == true);
36 
37 alias useOverloadSet = Alias!(__traits(getOverloads, S, "use"))[0];
38 alias useOverloadSet = Alias!(__traits(getOverloads, S, "use"))[1];
39 alias useOverloadSet = Alias!(__traits(getOverloads, S, "use"))[2];
40 
41 static assert(useOverloadSet(41) == 42);
42 //static assert(useOverloadSet('@') == false);
43 //static assert(useOverloadSet('7') == true);
44 static assert(useOverloadSet("Voldemort") == 'V');
45 
46 template AliasTuple(T...)
47 {
48     alias expand = T;
49 }
50 
51 template applyN(alias fun, Tuples...)
52     if (Tuples.length > 0)
53 {
54     static if (Tuples.length == 1)
55         alias applyN = apply!(fun, Tuples[0].expand);
56     else
57         alias applyN = applyN!(
58             apply!(fun, Tuples[0].expand),
59             Tuples[1 .. $]);
60 }
61 
62 //alias AT = AliasTuple;
63 //applyN!(Overloads, AT!(S, "use"), atIndex, 2, "asd");
64 //applyN!("use", ApplyLeft!(Overloads, S), ApplyLeft!(atIndex, 2)
65 
66 static assert(
67     apply!(apply!(atIndex, 2, apply!(Overloads, S, "use")), "asd") == 'a');

Meta