1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
// lesson 6: functions
//
// ::define<NAME, ::parameters<NAME, ...>, ::sequence<...>> defines a function
// a function sees nothing but its parameters. it gives back a type with
// ::return<TYPE>, or ::void if it never does. calling it is a type too:
// ::invoke_result_t<NAME, ::arguments<TYPE, ...>>, and every argument must be
// a ::decltype so it carries a value
::define<
::name<'s', 'q', 'u', 'a', 'r', 'e'>,
::parameters<::name<'x'>>,
::sequence<
::return<
::decltype(
::product<
::value_of<::name<'x'>>,
::value_of<::name<'x'>>
>
)
>::commit
>
>::commit;
// prints 25
::emit<
::invoke_result_t<
::name<'s', 'q', 'u', 'a', 'r', 'e'>,
::arguments<::decltype(::difference<'F', 'A'>)>
>
>::commit;
// a function can return anything a type can be, which includes a tuple of
// characters, which is the closest thing to a string you will get
::define<
::name<'g', 'r', 'e', 'e', 't'>,
::parameters<>,
::sequence<
::return<
::tuple<
::integral_constant<::char, ::difference<'h', '\0'>>,
::integral_constant<::char, ::difference<'e', '\0'>>,
::integral_constant<::char, ::difference<'y', '\0'>>
>
>::commit
>
>::commit;
::emit<
::invoke_result_t<
::name<'g', 'r', 'e', 'e', 't'>,
::arguments<>
>
>::commit;
// the result is a type. to use it as a value in arithmetic, ::declval<T>() gets
// the value back out. the parentheses are mandatory. it is a function, after all
// this prints 10
::emit<
::decltype(
::sum<
::declval<
::invoke_result_t<
::name<'s', 'q', 'u', 'a', 'r', 'e'>,
::arguments<::decltype(::difference<'D', 'A'>)>
>
>(),
::difference<'B', 'A'>
>
)
>::commit;
// recursion works, because nothing stopped it. factorial of 5
::define<
::name<'f', 'a', 'c', 't'>,
::parameters<::name<'n'>>,
::sequence<
::enable_if_t<
::less<
::value_of<::name<'n'>>,
::difference<'B', 'A'>
>::value,
::sequence<
::return<::decltype(::difference<'B', 'A'>)>::commit
>
>::commit,
::return<
::decltype(
::product<
::value_of<::name<'n'>>,
::declval<
::invoke_result_t<
::name<'f', 'a', 'c', 't'>,
::arguments<
::decltype(
::sum<
::value_of<::name<'n'>>,
::difference<'A', 'B'>
>
)
>
>
>()
>
)
>::commit
>
>::commit;
::emit<
::invoke_result_t<
::name<'f', 'a', 'c', 't'>,
::arguments<::decltype(::difference<'F', 'A'>)>
>
>::commit;
|