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