Skip to content

Commit 36efc91

Browse files
committed
Functional basics
1 parent 3fca8aa commit 36efc91

22 files changed

+841
-188
lines changed

NOTES.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
Apparently VC++ 2017 is not quite ready for
22

33
```c++
4-
template <auto v> struct value_t {
5-
using eval = value_t;
4+
template <auto v> struct value_c {
5+
using eval = value_c;
66
using type = decltype(v);
77
static constexpr auto value = v;
88
};

README.md

+80
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,83 @@
33
Non-strict template metaprogramming primitives for C++.
44

55
See [`synopsis.hpp`](provides/include/lax_v1/synopsis.hpp) for the API.
6+
7+
## <a id="contents"></a> [](#contents) [Contents](#contents)
8+
9+
- [Legend](#legend)
10+
- [Glossary](#glossary)
11+
- [Currying](#currying)
12+
- [Meta expression](#meta-expression)
13+
- [Meta function](#meta-function)
14+
- [Meta value](#meta-value)
15+
- [Non-strict evaluation](#non-strict-evaluation)
16+
- [Motivation](#motivation)
17+
- [References](#references)
18+
19+
## <a id="legend"></a> [](#contents) [Legend](#legend)
20+
21+
- `_m` [meta expression](#meta-expression) template
22+
- `_c` [meta value](#meta-value) or meta value template
23+
- `_p` primitive (internal type alias or meta expression template or class)
24+
- `_t` type alias (from C++11)
25+
- `_v` value constexpr (from C++17)
26+
27+
## <a id="glossary"></a> [](#contents) [Glossary](#glossary)
28+
29+
### <a id="currying"></a> [](#contents) [Currying](#currying)
30+
31+
### <a id="meta-expression"></a> [](#contents) [Meta expression](#meta-expression)
32+
33+
A lax meta expression is a type that is a subtype of a single
34+
[meta value](#meta-value) and includes no other members aside from those defined
35+
by that meta value.
36+
37+
```c++
38+
using a_meta_expression = add_m<auto_c<1>, auto_c<2>>;
39+
struct also_a_meta_expression : a_meta_expression {};
40+
```
41+
42+
Lax meta expression templates are typically [curried](#curried) and produce
43+
[meta functions](#meta-function) when partially applied.
44+
45+
### <a id="meta-function"></a> [≡](#contents) [Meta function](#meta-function)
46+
47+
A lax meta function is a [meta value](#meta-value) that has a static `arity`
48+
constant and an inner type template `template_m` that takes at least `arity`
49+
types as arguments and whose result is a [meta expression](#meta-expression).
50+
51+
```c++
52+
struct a_meta_function_c {
53+
using eval = a_meta_function_c;
54+
static constexpr size_t arity = N;
55+
template <class Actual_1, ..., class Actual_N>
56+
struct template_m : a_meta_expression {};
57+
};
58+
```
59+
60+
Lax higher-order meta functions take meta functions as arguments and use them
61+
via the `apply_m` [meta expression template](#meta-expression-template). Note
62+
that `template_m` need not support [currying](#currying) like
63+
[meta expression templates](#meta-expression-template), because `apply_m` takes
64+
care of that.
65+
66+
### <a id="meta-value"></a> [≡](#contents) [Meta value](#meta-value)
67+
68+
A lax meta value is a [meta expression](#meta-expression) whose inner `eval`
69+
type is an alias for the meta expression itself.
70+
71+
```c++
72+
struct a_meta_value_c {
73+
using eval = a_meta_value_c;
74+
// and additional members depending on value
75+
};
76+
```
77+
78+
Meta values also typically include additional static constants, types, or type
79+
templates.
80+
81+
### <a id="non-strict-evaluation"></a> [≡](#contents) [Non-strict evaluation](#non-strict-evaluation)
82+
83+
## <a id="motivation"></a> [≡](#contents) [Motivation](#motivation)
84+
85+
## <a id="references"></a> [≡](#contents) [References](#references)

internals/testing/arithmetic_test.cpp

+15-20
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,29 @@
11
#include "lax_v1/arithmetic.hpp"
2-
#include "lax_v1/force.hpp"
32

43
#include "config.hpp"
54

65
#include <type_traits>
76

8-
static_assert(
9-
std::is_same_v<
10-
lax::force_t<lax::add_m<lax::value_t<short, 1>, lax::value_t<long, 2>>>,
11-
lax::value_t<long, 3>>);
7+
static_assert(std::is_same_v<lax::force_c<lax::adds_m<lax::value_c<short, 1>,
8+
lax::value_c<long, 2>>>,
9+
lax::value_c<long, 3>>);
1210

1311
static_assert(
14-
std::is_same_v<
15-
lax::force_t<lax::mod_m<lax::value_t<int, 2>, lax::value_t<int, 2>>>,
16-
lax::value_t<int, 0>>);
12+
std::is_same_v<lax::force_c<lax::mod_m<lax::auto_c<2>, lax::auto_c<2>>>,
13+
lax::auto_c<0>>);
1714

18-
static_assert(
19-
std::is_same_v<
20-
lax::force_t<lax::mul_m<lax::value_t<int, 1>, lax::value_t<short, 2>>>,
21-
lax::value_t<int, 2>>);
15+
static_assert(std::is_same_v<
16+
lax::force_c<lax::muls_m<lax::auto_c<1>, lax::value_c<short, 2>>>,
17+
lax::auto_c<2>>);
2218

2319
static_assert(
2420
std::is_same_v<
25-
lax::force_t<lax::div_m<lax::value_t<short, 6>, lax::value_t<char, 2>>>,
26-
lax::value_t<int, 3>>);
21+
lax::force_c<lax::div_m<lax::value_c<short, 6>, lax::value_c<char, 2>>>,
22+
lax::auto_c<3>>);
2723

28-
static_assert(
29-
std::is_same_v<
30-
lax::force_t<lax::sub_m<lax::value_t<int, 3>, lax::value_t<char, 2>>>,
31-
lax::value_t<int, 1>>);
24+
static_assert(std::is_same_v<
25+
lax::force_c<lax::sub_m<lax::auto_c<3>, lax::value_c<char, 2>>>,
26+
lax::auto_c<1>>);
3227

33-
static_assert(std::is_same_v<lax::force_t<lax::neg_m<lax::value_t<short, 3>>>,
34-
lax::value_t<int, -3>>);
28+
static_assert(std::is_same_v<lax::force_c<lax::neg_m<lax::value_c<short, 3>>>,
29+
lax::auto_c<-3>>);

internals/testing/comparison_test.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
#include "config.hpp"
44

5-
static_assert(
6-
lax::value_of_v<lax::gt_m<lax::value_t<int, 2>, lax::value_t<int, 1>>>);
5+
static_assert(lax::gt_m<lax::auto_c<2>, lax::auto_c<1>>::value);
76

8-
static_assert(
9-
!lax::value_of_v<lax::eq_m<lax::value_t<int, 2>, lax::value_t<int, 1>>>);
7+
static_assert(!lax::eq_m<lax::auto_c<2>, lax::auto_c<1>>::value);
+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
#include "lax_v1/lax.hpp"
2+
13
int main() { return 0; }

internals/testing/core_test.cpp

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#include "lax_v1/arithmetic.hpp"
2+
#include "lax_v1/core.hpp"
3+
#include "lax_v1/functional.hpp"
4+
#include "lax_v1/type_traits.hpp"
5+
6+
#include "config.hpp"
7+
8+
struct X;
9+
struct Y;
10+
struct Z;
11+
12+
static_assert(
13+
std::is_same_v<
14+
lax::force_deep_c<
15+
lax::seq_c<lax::add_m<>,
16+
lax::add_m<lax::add_m<lax::auto_c<1>, lax::auto_c<2>>>,
17+
lax::remove_pointer_m<lax::type_c<void *>>,
18+
lax::seq_c<lax::add_m<lax::auto_c<1>, lax::auto_c<2>>>,
19+
lax::fn_c<lax::seq_c<X, Y, Z>, lax::adds_m<X, Y, Z>>>>,
20+
lax::seq_c<
21+
lax::from_primitive_c<lax::add_p, 2>,
22+
lax::closure_c<lax::from_primitive_c<lax::add_p, 2>,
23+
lax::add_m<lax::auto_c<1>, lax::auto_c<2>>>,
24+
lax::type_c<void>,
25+
lax::seq_c<lax::auto_c<3>>,
26+
lax::function_c<
27+
X,
28+
lax::function_c<Y,
29+
lax::function_c<Z, lax::adds_m<X, Y, Z>>>>>>);

internals/testing/functional_test.cpp

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#include "lax_v1/arithmetic.hpp"
2+
#include "lax_v1/comparison.hpp"
3+
#include "lax_v1/functional.hpp"
4+
#include "lax_v1/type_traits.hpp"
5+
6+
#include "config.hpp"
7+
8+
static_assert(lax::apply_m<lax::compose_m<lax::neg_m<>, lax::neg_m<>>,
9+
lax::auto_c<2>>::value == 2);
10+
11+
static_assert(lax::apply_m<lax::composes_m<lax::inc_m<>,
12+
lax::neg_m<>,
13+
lax::add_m<lax::auto_c<-1>>>,
14+
lax::auto_c<1>>::value == 1);
15+
16+
static_assert(
17+
lax::apply_m<
18+
lax::pipes_m<lax::add_m<lax::auto_c<1>>, lax::neg_m<>, lax::dec_m<>>,
19+
lax::auto_c<1>>::value == -3);
20+
21+
static_assert(lax::thru_m<lax::auto_c<1>,
22+
lax::add_m<lax::auto_c<1>>,
23+
lax::neg_m<>,
24+
lax::add_m<lax::auto_c<-1>>,
25+
lax::eq_m<lax::auto_c<-3>>>::value == true);
26+
27+
struct V;
28+
29+
static_assert(lax::apply_m<lax::function_c<V, lax::add_m<V, lax::neg_m<V>>>,
30+
lax::auto_c<1>>::value == 0);
31+
32+
static_assert(lax::thru_m<lax::type_c<short * [1]>,
33+
lax::remove_all_extents_m<>,
34+
lax::remove_pointer_m<>,
35+
lax::alignment_of_m<>>::value == alignof(short));
36+
37+
static_assert(lax::thru_m<lax::auto_c<0>,
38+
lax::div_m<lax::auto_c<0>>,
39+
lax::constant_m<lax::auto_c<101>>>::value == 101);
40+
41+
template <class T>
42+
using adhoc_t = lax::as_type_trait_t<
43+
lax::pipe_m<lax::remove_all_extents_m<>, lax::remove_pointer_m<>>,
44+
T>;
45+
46+
static_assert(std::is_same_v<adhoc_t<int * [2][2]>, int>);
47+
48+
template <class T>
49+
inline constexpr auto adhoc_v = lax::as_value_trait_v<
50+
lax::pipe_m<lax::remove_all_extents_m<>, lax::alignment_of_m<>>,
51+
T>;
52+
53+
static_assert(adhoc_v<int * [2][2]> == alignof(int *));
54+
55+
struct F;
56+
57+
template <int value>
58+
inline constexpr auto factorial_v = lax::apply_m<
59+
lax::fix_m<lax::fn_c<
60+
lax::seq_c<F, V>,
61+
lax::if_m<
62+
lax::eq_m<lax::auto_c<0>, V>,
63+
lax::auto_c<1>,
64+
lax::mul_m<V, lax::apply_m<F, lax::sub_m<V, lax::auto_c<1>>>>>>>,
65+
lax::auto_c<value>>::value;
66+
67+
static_assert(factorial_v<5> == 120);

internals/testing/logical_test.cpp

+14-8
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22

33
#include "config.hpp"
44

5-
static_assert(
6-
lax::value_of_v<
7-
lax::if_m<lax::and_m<>, lax::value_t<int, 1>, lax::value_t<int, 2>>> ==
8-
1);
5+
static_assert(lax::if_m<lax::ands_m<>, lax::auto_c<1>, lax::auto_c<2>>::value ==
6+
1);
7+
8+
static_assert(lax::if_m<lax::ors_m<>, lax::auto_c<1>, lax::auto_c<2>>::value ==
9+
2);
10+
11+
static_assert(!lax::and_m<lax::false_c,
12+
lax::div_m<lax::auto_c<1>, lax::auto_c<0>>>::value);
913

1014
static_assert(
11-
lax::value_of_v<
12-
lax::if_m<lax::or_m<>, lax::value_t<int, 1>, lax::value_t<int, 2>>> ==
13-
2);
15+
lax::or_m<lax::true_c, lax::div_m<lax::auto_c<1>, lax::auto_c<0>>>::value);
16+
17+
static_assert(lax::not_m<lax::false_c>::value);
1418

15-
static_assert(lax::value_of_v<lax::not_m<lax::false_t>>);
19+
static_assert(lax::switch_m<lax::case_c<lax::false_c, lax::auto_c<2>>,
20+
lax::case_c<lax::true_c, lax::auto_c<1>>,
21+
lax::default_c<lax::auto_c<3>>>::value == 1);

internals/testing/type_traits_test.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@
44

55
#include "config.hpp"
66

7-
static_assert(lax::value_of_v<lax::is_array_m<lax::type_t<int[2]>>>);
7+
static_assert(lax::is_array_m<lax::type_c<int[2]>>::value);
88

99
template <class Value>
1010
struct is_stored_plain_m
1111
: lax::or_m<
1212
lax::and_m<
1313
lax::is_pointer_m<Value>,
14-
lax::lte_m<lax::value_t<size_t, 2>,
14+
lax::lte_m<lax::auto_c<2>,
1515
lax::alignment_of_m<lax::remove_pointer_m<Value>>>>,
1616
lax::and_m<lax::is_array_m<Value>,
1717
is_stored_plain_m<lax::remove_all_extents_m<Value>>>> {};
1818

1919
template <class Value>
2020
static inline constexpr bool is_stored_plain_v =
21-
lax::value_of_v<is_stored_plain_m<lax::type_t<Value>>>;
21+
is_stored_plain_m<lax::type_c<Value>>::value;
2222

2323
static_assert(!is_stored_plain_v<char>);
2424
static_assert(!is_stored_plain_v<char *>);
2525
static_assert(is_stored_plain_v<int *>);
2626
static_assert(is_stored_plain_v<int * [2]>);
27+
28+
static_assert(!lax::is_same_m<lax::type_c<void>, lax::type_c<int>>::value);

internals/testing/value_test.cpp

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
#include "lax_v1/value.hpp"
1+
#include "lax_v1/core.hpp"
22

33
#include "config.hpp"
44

55
#include <type_traits>
66

7-
static_assert(std::is_same_v<lax::value_t<bool, true>::value_type, bool>);
7+
static_assert(std::is_same_v<lax::auto_c<true>::value_type, bool>);
88

9-
static_assert(std::is_same_v<lax::value_t<char, 'x'>::value_type, char>);
10-
static_assert(std::is_same_v<lax::value_t<short, 101>::value_type, short>);
11-
static_assert(std::is_same_v<lax::value_t<int, 101>::value_type, int>);
9+
static_assert(std::is_same_v<lax::auto_c<'x'>::value_type, char>);
10+
static_assert(std::is_same_v<lax::value_c<short, 101>::value_type, short>);
11+
static_assert(std::is_same_v<lax::auto_c<101>::value_type, int>);
1212
static_assert(
13-
std::is_same_v<lax::value_t<unsigned, 101u>::value_type, unsigned>);
14-
static_assert(std::is_same_v<lax::value_t<long, 101l>::value_type, long>);
15-
static_assert(std::is_same_v<lax::value_t<unsigned long, 101ul>::value_type,
13+
std::is_same_v<lax::value_c<unsigned, 101u>::value_type, unsigned>);
14+
static_assert(std::is_same_v<lax::value_c<long, 101l>::value_type, long>);
15+
static_assert(std::is_same_v<lax::value_c<unsigned long, 101ul>::value_type,
1616
unsigned long>);
1717
static_assert(
18-
std::is_same_v<lax::value_t<unsigned long long, 101ull>::value_type,
18+
std::is_same_v<lax::value_c<unsigned long long, 101ull>::value_type,
1919
unsigned long long>);

0 commit comments

Comments
 (0)