decorate.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*=============================================================================
  2. Copyright (c) 2015 Paul Fultz II
  3. decorate.h
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #ifndef BOOST_HOF_GUARD_DECORATE_H
  8. #define BOOST_HOF_GUARD_DECORATE_H
  9. /// decorate
  10. /// ========
  11. ///
  12. /// Description
  13. /// -----------
  14. ///
  15. /// The `decorate` function adaptor helps create simple function decorators.
  16. ///
  17. /// A function adaptor takes a function and returns a new functions whereas a
  18. /// decorator takes some parameters and returns a function adaptor. The
  19. /// `decorate` function adaptor will return a decorator that returns a
  20. /// function adaptor. Eventually, it will invoke the function with the user-
  21. /// provided parameter and function.
  22. ///
  23. /// Synopsis
  24. /// --------
  25. ///
  26. /// template<class F>
  27. /// constexpr decorate_adaptor<F> decorate(F f);
  28. ///
  29. /// Semantics
  30. /// ---------
  31. ///
  32. /// assert(decorate(f)(x)(g)(xs...) == f(x, g, xs...));
  33. ///
  34. /// Requirements
  35. /// ------------
  36. ///
  37. /// F must be:
  38. ///
  39. /// * [ConstInvocable](ConstInvocable)
  40. /// * MoveConstructible
  41. ///
  42. /// Example
  43. /// -------
  44. ///
  45. /// #include <boost/hof.hpp>
  46. /// #include <cassert>
  47. /// #include <iostream>
  48. /// #include <string>
  49. /// using namespace boost::hof;
  50. ///
  51. /// struct logger_f
  52. /// {
  53. /// template<class F, class... Ts>
  54. /// auto operator()(const std::string& message, F&& f, Ts&&... xs) const
  55. /// -> decltype(f(std::forward<Ts>(xs)...))
  56. /// {
  57. /// // Message to print out when the function is called
  58. /// std::cout << message << std::endl;
  59. /// // Call the function
  60. /// return f(std::forward<Ts>(xs)...);
  61. /// }
  62. /// };
  63. /// // The logger decorator
  64. /// BOOST_HOF_STATIC_FUNCTION(logger) = boost::hof::decorate(logger_f());
  65. ///
  66. /// struct sum_f
  67. /// {
  68. /// template<class T, class U>
  69. /// T operator()(T x, U y) const
  70. /// {
  71. /// return x+y;
  72. /// }
  73. /// };
  74. ///
  75. /// BOOST_HOF_STATIC_FUNCTION(sum) = sum_f();
  76. /// int main() {
  77. /// // Use the logger decorator to print "Calling sum" when the function is called
  78. /// assert(3 == logger("Calling sum")(sum)(1, 2));
  79. /// }
  80. ///
  81. #include <boost/hof/reveal.hpp>
  82. #include <boost/hof/detail/delegate.hpp>
  83. #include <boost/hof/detail/move.hpp>
  84. #include <boost/hof/detail/make.hpp>
  85. #include <boost/hof/detail/callable_base.hpp>
  86. #include <boost/hof/detail/static_const_var.hpp>
  87. #include <boost/hof/detail/compressed_pair.hpp>
  88. namespace boost { namespace hof { namespace detail {
  89. template<class D, class T, class F>
  90. struct decorator_invoke
  91. // : compressed_pair<compressed_pair<F, T>, D>
  92. : compressed_pair<compressed_pair<D, T>, F>
  93. {
  94. // typedef compressed_pair<F, T> base;
  95. typedef compressed_pair<compressed_pair<D, T>, F> base;
  96. BOOST_HOF_INHERIT_CONSTRUCTOR(decorator_invoke, base)
  97. template<class... Ts>
  98. constexpr const compressed_pair<D, T>& get_pair(Ts&&... xs) const noexcept
  99. {
  100. return this->first(xs...);
  101. }
  102. template<class... Ts>
  103. constexpr const F& base_function(Ts&&... xs) const noexcept
  104. {
  105. return this->second(xs...);
  106. }
  107. template<class... Ts>
  108. constexpr const D& get_decorator(Ts&&... xs) const noexcept
  109. {
  110. return this->get_pair(xs...).first(xs...);
  111. }
  112. template<class... Ts>
  113. constexpr const T& get_data(Ts&&... xs) const noexcept
  114. {
  115. return this->get_pair(xs...).second(xs...);
  116. }
  117. BOOST_HOF_RETURNS_CLASS(decorator_invoke);
  118. struct decorator_invoke_failure
  119. {
  120. template<class Failure>
  121. struct apply
  122. {
  123. template<class... Ts>
  124. struct of
  125. : Failure::template of<const T&, const F&, Ts...>
  126. {};
  127. };
  128. };
  129. struct failure
  130. : failure_map<decorator_invoke_failure, D>
  131. {};
  132. template<class... Ts>
  133. constexpr BOOST_HOF_SFINAE_RESULT(const D&, id_<const T&>, id_<const F&>, id_<Ts>...)
  134. operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
  135. (
  136. BOOST_HOF_MANGLE_CAST(const D&)(BOOST_HOF_CONST_THIS->get_decorator(xs...))(
  137. BOOST_HOF_MANGLE_CAST(const T&)(BOOST_HOF_CONST_THIS->get_data(xs...)),
  138. BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)),
  139. BOOST_HOF_FORWARD(Ts)(xs)...
  140. )
  141. );
  142. };
  143. template<class D, class T>
  144. struct decoration
  145. : compressed_pair<D, T>
  146. {
  147. typedef compressed_pair<D, T> base;
  148. BOOST_HOF_INHERIT_CONSTRUCTOR(decoration, base)
  149. template<class... Ts>
  150. constexpr const D& get_decorator(Ts&&... xs) const noexcept
  151. {
  152. return this->first(xs...);
  153. }
  154. template<class... Ts>
  155. constexpr const T& get_data(Ts&&... xs) const noexcept
  156. {
  157. return this->second(xs...);
  158. }
  159. template<class F>
  160. constexpr decorator_invoke<D, T, detail::callable_base<F>> operator()(F f) const
  161. BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(decorator_invoke<D, T, detail::callable_base<F>>, compressed_pair<D, T>, detail::callable_base<F>&&))
  162. {
  163. return decorator_invoke<D, T, detail::callable_base<F>>(
  164. *this, static_cast<detail::callable_base<F>&&>(f)
  165. );
  166. }
  167. };
  168. }
  169. template<class F>
  170. struct decorate_adaptor : detail::callable_base<F>
  171. {
  172. typedef decorate_adaptor fit_rewritable1_tag;
  173. typedef detail::callable_base<F> base;
  174. BOOST_HOF_INHERIT_CONSTRUCTOR(decorate_adaptor, detail::callable_base<F>)
  175. template<class... Ts>
  176. constexpr const base& base_function(Ts&&... xs) const noexcept
  177. {
  178. return boost::hof::always_ref(*this)(xs...);
  179. }
  180. // TODO: Add predicate for constraints
  181. template<class T>
  182. constexpr detail::decoration<base, T> operator()(T x) const
  183. BOOST_HOF_NOEXCEPT(BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(base, const base&) && BOOST_HOF_IS_NOTHROW_CONSTRUCTIBLE(T, T&&))
  184. {
  185. return detail::decoration<base, T>(this->base_function(x), static_cast<T&&>(x));
  186. }
  187. };
  188. BOOST_HOF_DECLARE_STATIC_VAR(decorate, detail::make<decorate_adaptor>);
  189. }} // namespace boost::hof
  190. #endif