]>
Commit | Line | Data |
---|---|---|
b32b8144 | 1 | // Copyright Louis Dionne 2013-2017 |
7c673cae FG |
2 | // Distributed under the Boost Software License, Version 1.0. |
3 | // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) | |
4 | ||
5 | #ifndef TEST_SUPPORT_IDENTITY_HPP | |
6 | #define TEST_SUPPORT_IDENTITY_HPP | |
7 | ||
8 | #include <boost/hana/chain.hpp> | |
9 | #include <boost/hana/eval_if.hpp> | |
10 | #include <boost/hana/functional/compose.hpp> | |
11 | #include <boost/hana/functional/partial.hpp> | |
12 | #include <boost/hana/fwd/adjust_if.hpp> | |
13 | #include <boost/hana/fwd/ap.hpp> | |
14 | #include <boost/hana/fwd/equal.hpp> | |
15 | #include <boost/hana/fwd/flatten.hpp> | |
16 | #include <boost/hana/fwd/less.hpp> | |
17 | #include <boost/hana/fwd/lift.hpp> | |
18 | #include <boost/hana/lazy.hpp> | |
19 | #include <boost/hana/transform.hpp> | |
20 | ||
21 | #include <type_traits> | |
22 | ||
23 | ||
24 | struct Identity; | |
25 | ||
26 | template <typename T> | |
27 | struct identity_t { | |
28 | T value; | |
29 | using hana_tag = Identity; | |
30 | }; | |
31 | ||
32 | struct make_identity { | |
33 | template <typename T> | |
34 | constexpr identity_t<typename std::decay<T>::type> operator()(T&& t) const { | |
35 | return {static_cast<T&&>(t)}; | |
36 | } | |
37 | }; | |
38 | ||
39 | constexpr make_identity identity{}; | |
40 | ||
41 | ||
42 | namespace boost { namespace hana { | |
43 | ////////////////////////////////////////////////////////////////////////// | |
44 | // Comparable | |
45 | ////////////////////////////////////////////////////////////////////////// | |
46 | template <> | |
47 | struct equal_impl<Identity, Identity> { | |
48 | template <typename Id1, typename Id2> | |
49 | static constexpr auto apply(Id1 x, Id2 y) | |
50 | { return hana::equal(x.value, y.value); } | |
51 | }; | |
52 | ||
53 | ////////////////////////////////////////////////////////////////////////// | |
54 | // Orderable | |
55 | ////////////////////////////////////////////////////////////////////////// | |
56 | template <> | |
57 | struct less_impl<Identity, Identity> { | |
58 | template <typename Id1, typename Id2> | |
59 | static constexpr auto apply(Id1 x, Id2 y) | |
60 | { return hana::less(x.value, y.value); } | |
61 | }; | |
62 | ||
63 | ////////////////////////////////////////////////////////////////////////// | |
64 | // Functor | |
65 | // | |
66 | // Define either one to select which MCD is used: | |
67 | // BOOST_HANA_TEST_FUNCTOR_TRANSFORM_MCD | |
68 | // BOOST_HANA_TEST_FUNCTOR_ADJUST_MCD_MCD | |
69 | // | |
70 | // If neither is defined, the MCD used is unspecified. | |
71 | ////////////////////////////////////////////////////////////////////////// | |
72 | #ifdef BOOST_HANA_TEST_FUNCTOR_TRANSFORM_MCD | |
73 | template <> | |
74 | struct transform_impl<Identity> { | |
75 | template <typename Id, typename F> | |
76 | static constexpr auto apply(Id self, F f) | |
77 | { return ::identity(f(self.value)); } | |
78 | }; | |
79 | #else | |
80 | template <> | |
81 | struct adjust_if_impl<Identity> { | |
82 | struct get_value { | |
83 | template <typename T> | |
84 | constexpr auto operator()(T t) const { return t.value; } | |
85 | }; | |
86 | ||
87 | template <typename Id, typename P, typename F> | |
88 | static constexpr auto apply(Id self, P p, F f) { | |
89 | auto x = hana::eval_if(p(self.value), | |
90 | hana::make_lazy(hana::compose(f, get_value{}))(self), | |
91 | hana::make_lazy(get_value{})(self) | |
92 | ); | |
93 | return ::identity(x); | |
94 | } | |
95 | }; | |
96 | #endif | |
97 | ||
98 | ////////////////////////////////////////////////////////////////////////// | |
99 | // Applicative | |
100 | // | |
101 | // Define either one to select which MCD is used: | |
102 | // BOOST_HANA_TEST_APPLICATIVE_FULL_MCD | |
103 | // BOOST_HANA_TEST_APPLICATIVE_MONAD_MCD | |
104 | // | |
105 | // If neither is defined, the MCD used is unspecified. | |
106 | ////////////////////////////////////////////////////////////////////////// | |
107 | template <> | |
108 | struct lift_impl<Identity> { | |
109 | template <typename X> | |
110 | static constexpr auto apply(X x) | |
111 | { return ::identity(x); } | |
112 | }; | |
113 | #ifdef BOOST_HANA_TEST_APPLICATIVE_FULL_MCD | |
114 | template <> | |
115 | struct ap_impl<Identity> { | |
116 | template <typename F, typename X> | |
117 | static constexpr auto apply(F f, X x) | |
118 | { return ::identity(f.value(x.value)); } | |
119 | }; | |
120 | #else | |
121 | template <> | |
122 | struct ap_impl<Identity> { | |
123 | template <typename F, typename X> | |
124 | static constexpr decltype(auto) apply(F&& f, X&& x) { | |
125 | return hana::chain( | |
126 | static_cast<F&&>(f), | |
127 | hana::partial(hana::transform, static_cast<X&&>(x)) | |
128 | ); | |
129 | } | |
130 | }; | |
131 | #endif | |
132 | ||
133 | ////////////////////////////////////////////////////////////////////////// | |
134 | // Monad | |
135 | // | |
136 | // Define either one to select which MCD is used: | |
137 | // BOOST_HANA_TEST_MONAD_FLATTEN_MCD | |
138 | // BOOST_HANA_TEST_MONAD_CHAIN_MCD | |
139 | // | |
140 | // If neither is defined, the MCD used is unspecified. | |
141 | ////////////////////////////////////////////////////////////////////////// | |
142 | #ifdef BOOST_HANA_TEST_MONAD_FLATTEN_MCD | |
143 | template <> | |
144 | struct flatten_impl<Identity> { | |
145 | template <typename Id> | |
146 | static constexpr auto apply(Id self) | |
147 | { return self.value; } | |
148 | }; | |
149 | #else | |
150 | template <> | |
151 | struct chain_impl<Identity> { | |
152 | template <typename X, typename F> | |
153 | static constexpr auto apply(X x, F f) | |
154 | { return f(x.value); } | |
155 | }; | |
156 | #endif | |
157 | }} // end namespace boost::hana | |
158 | ||
159 | #endif // !TEST_SUPPORT_IDENTITY_HPP |