identity.hpp 4.9 KB

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