-
Notifications
You must be signed in to change notification settings - Fork 0
/
infix-on.cc
107 lines (85 loc) · 1.94 KB
/
infix-on.cc
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
#include <type_traits>
#include <functional>
// (f `on` m) a b = f (m a) (m b)
template <class F, class M>
struct on_exec_t {
F f;
M m;
template <class A, class B>
constexpr auto operator()(A&& a, B&& b) &
-> decltype(f(m((A&&)a), m((B&&)b)))
{
return f(m((A&&)a), m((B&&)b));
}
template <class A, class B>
constexpr auto operator()(A&& a, B&& b) const&
-> decltype(f(m((A&&)a), m((B&&)b)))
{
return f(m((A&&)a), m((B&&)b));
}
template <class A, class B>
constexpr auto operator()(A&& a, B&& b) &&
-> decltype(((F&&)f)(((M&&)m)((A&&)a), ((M&&)m)((B&&)b)))
{
return ((F&&)f)(((M&&)m)((A&&)a), ((M&&)m)((B&&)b));
}
template <class A, class B>
constexpr auto operator()(A&& a, B&& b) const&&
-> decltype(((F const&&)f)(((M const&&)m)((A&&)a), ((M const&&)m)((B&&)b)))
{
return ((F const&&)f)(((M const&&)m)((A&&)a), ((M const&&)m)((B&&)b));
}
};
template <class M>
struct on_partial_t {
M m;
template <class F>
on_exec_t<typename std::decay<F>::type, M>
constexpr operator()(F&& f) const&
{
return { (F&&)f, m };
}
template <class F>
on_exec_t<typename std::decay<F>::type, M>
constexpr operator()(F&& f) &&
{
return { (F&&)f, (M&&) m };
}
};
template <class M>
on_partial_t<typename std::decay<M>::type>
constexpr on(M&& m)
{
return { (M&&)m };
}
// x & f = f x
template <class F, class X>
constexpr auto operator&(X&& x, F&& f)
-> decltype(((F&&)f)((X&&)x))
{
return ((F&&)f)((X&&)x);
}
// extract a member by .*
template <class Mem>
struct extract_t {
Mem m;
template <class X>
constexpr auto operator()(X&& x) const
-> decltype(((X&&)x).*m)
{
return ((X&&)x).*m;
}
};
template <class Mem>
extract_t<typename std::decay<Mem>::type>
constexpr extract(Mem&& m)
{
return { (Mem&&)m };
}
int main()
{
struct T { int x; };
constexpr auto comp = std::less<int>() & on(extract(&T::x));
static_assert(comp(T{1}, T{2}), "1 < 2");
return 0;
}