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 69namespace boost { namespace hof { 70// TODO: Support non-classes as well 71template<class F> 72struct indirect_adaptor : F 73{ 74 typedef indirect_adaptor fit_rewritable1_tag; 75 BOOST_HOF_INHERIT_CONSTRUCTOR(indirect_adaptor, F); 76 77 template<class... Ts> 78 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 97template<class F> 98struct indirect_adaptor<F*> 99{ 100 typedef indirect_adaptor fit_rewritable1_tag; 101 F* f; 102 constexpr indirect_adaptor() noexcept 103 {} 104 105 constexpr indirect_adaptor(F* x) noexcept 106 : f(x) 107 {} 108 109 template<class... Ts> 110 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 129BOOST_HOF_DECLARE_STATIC_VAR(indirect, detail::make<indirect_adaptor>); 130 131}} // namespace boost::hof 132 133#endif 134