• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Louis Dionne 2013-2017
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>
operator ()make_identity34     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>
applyboost::hana::equal_impl49         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>
applyboost::hana::less_impl59         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>
applyboost::hana::transform_impl76         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>
operator ()boost::hana::adjust_if_impl::get_value84             constexpr auto operator()(T t) const { return t.value; }
85         };
86 
87         template <typename Id, typename P, typename F>
applyboost::hana::adjust_if_impl88         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>
applyboost::hana::lift_impl110         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>
applyboost::hana::ap_impl117         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>
applyboost::hana::ap_impl124         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>
applyboost::hana::flatten_impl146         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>
applyboost::hana::chain_impl153         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
160