1 /*============================================================================= 2 Copyright (c) 2014 Paul Fultz II 3 indirect.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 8 #ifndef BOOST_HOF_GUARD_FUNCTION_INDIRECT_H 9 #define BOOST_HOF_GUARD_FUNCTION_INDIRECT_H 10 11 /// indirect 12 /// ======== 13 /// 14 /// Description 15 /// ----------- 16 /// 17 /// The `indirect` function adaptor dereferences the object before calling it. 18 /// 19 /// Synopsis 20 /// -------- 21 /// 22 /// template<class F> 23 /// constexpr indirect_adaptor<F> indirect(F f); 24 /// 25 /// Semantics 26 /// --------- 27 /// 28 /// assert(indirect(f)(xs...) == (*f)(xs...)); 29 /// 30 /// Requirements 31 /// ------------ 32 /// 33 /// F must be: 34 /// 35 /// * MoveConstructible 36 /// * Dereferenceable 37 /// 38 /// Example 39 /// ------- 40 /// 41 /// #include <boost/hof.hpp> 42 /// #include <cassert> 43 /// #include <memory> 44 /// using namespace boost::hof; 45 /// 46 /// struct sum 47 /// { 48 /// template<class T, class U> 49 /// T operator()(T x, U y) const 50 /// { 51 /// return x+y; 52 /// } 53 /// }; 54 /// 55 /// int main() { 56 /// int r = indirect(std::make_unique<sum>())(3,2); 57 /// assert(r == 5); 58 /// } 59 /// 60 61 #include <boost/hof/detail/delegate.hpp> 62 #include <boost/hof/detail/result_of.hpp> 63 #include <boost/hof/reveal.hpp> 64 #include <boost/hof/always.hpp> 65 #include <boost/hof/detail/move.hpp> 66 #include <boost/hof/detail/make.hpp> 67 #include <boost/hof/detail/static_const_var.hpp> 68 69 namespace boost { namespace hof { 70 // TODO: Support non-classes as well 71 template<class F> 72 struct indirect_adaptor : F 73 { 74 typedef indirect_adaptor fit_rewritable1_tag; 75 BOOST_HOF_INHERIT_CONSTRUCTOR(indirect_adaptor, F); 76 77 template<class... Ts> base_functionboost::hof::indirect_adaptor78 constexpr const F& base_function(Ts&&... xs) const noexcept 79 { 80 return boost::hof::always_ref(*this)(xs...); 81 } 82 83 struct failure 84 : failure_for<decltype(*std::declval<F>())> 85 {}; 86 87 BOOST_HOF_RETURNS_CLASS(indirect_adaptor); 88 89 template<class... Ts> 90 constexpr BOOST_HOF_SFINAE_RESULT(decltype(*std::declval<F>()), id_<Ts>...) 91 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS 92 ( 93 (*BOOST_HOF_MANGLE_CAST(const F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_FORWARD(Ts)(xs)...) 94 ); 95 }; 96 97 template<class F> 98 struct indirect_adaptor<F*> 99 { 100 typedef indirect_adaptor fit_rewritable1_tag; 101 F* f; indirect_adaptorboost::hof::indirect_adaptor102 constexpr indirect_adaptor() noexcept 103 {} 104 indirect_adaptorboost::hof::indirect_adaptor105 constexpr indirect_adaptor(F* x) noexcept 106 : f(x) 107 {} 108 109 template<class... Ts> base_functionboost::hof::indirect_adaptor110 constexpr F& base_function(Ts&&...) const noexcept 111 { 112 return *f; 113 } 114 115 struct failure 116 : failure_for<F> 117 {}; 118 119 BOOST_HOF_RETURNS_CLASS(indirect_adaptor); 120 121 template<class... Ts> 122 constexpr BOOST_HOF_SFINAE_RESULT(F, id_<Ts>...) 123 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS 124 ( 125 (BOOST_HOF_MANGLE_CAST(F&)(BOOST_HOF_CONST_THIS->base_function(xs...)))(BOOST_HOF_FORWARD(Ts)(xs)...) 126 ); 127 }; 128 129 BOOST_HOF_DECLARE_STATIC_VAR(indirect, detail::make<indirect_adaptor>); 130 131 }} // namespace boost::hof 132 133 #endif 134