1/*============================================================================= 2 Copyright (c) 2014 Paul Fultz II 3 result.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_RESULT_H 9#define BOOST_HOF_GUARD_RESULT_H 10 11/// result 12/// ====== 13/// 14/// Description 15/// ----------- 16/// 17/// The `result` function adaptor sets the return type for the function, which 18/// can be useful when dealing with multiple overloads. Since the return type 19/// is no longer dependent on the parameters passed to the function, the 20/// `result_adaptor` provides a nested `result_type` that is the return type 21/// of the function. 22/// 23/// Synopsis 24/// -------- 25/// 26/// template<class Result, class F> 27/// constexpr result_adaptor<Result, F> result(F f); 28/// 29/// Requirements 30/// ------------ 31/// 32/// F must be: 33/// 34/// * [ConstInvocable](ConstInvocable) 35/// * MoveConstructible 36/// 37/// Example 38/// ------- 39/// 40/// #include <boost/hof.hpp> 41/// #include <cassert> 42/// 43/// struct id 44/// { 45/// template<class T> 46/// T operator()(T x) const 47/// { 48/// return x; 49/// } 50/// }; 51/// 52/// int main() { 53/// auto int_result = boost::hof::result<int>(id()); 54/// static_assert(std::is_same<decltype(int_result(true)), int>::value, "Not the same type"); 55/// } 56/// 57 58#include <boost/hof/detail/callable_base.hpp> 59#include <boost/hof/is_invocable.hpp> 60#include <boost/hof/always.hpp> 61#include <boost/hof/reveal.hpp> 62 63namespace boost { namespace hof { 64 65template<class Result, class F> 66struct result_adaptor : detail::callable_base<F> 67{ 68 BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>) 69 70 typedef Result result_type; 71 72 struct failure 73 : failure_for<detail::callable_base<F>> 74 {}; 75 76 template<class... Ts> 77 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const 78 { 79 return boost::hof::always_ref(*this)(xs...); 80 } 81 82 template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type> 83 constexpr result_type operator()(Ts&&... xs) const 84 { 85 return this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...); 86 }; 87}; 88 89template<class F> 90struct result_adaptor<void, F> : detail::callable_base<F> 91{ 92 BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>) 93 94 typedef void result_type; 95 96 template<class... Ts> 97 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const 98 { 99 return boost::hof::always_ref(*this)(xs...); 100 } 101 102 template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type> 103 constexpr typename detail::holder<Ts...>::type operator()(Ts&&... xs) const 104 { 105 return (typename detail::holder<Ts...>::type)this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...); 106 }; 107}; 108 109#if BOOST_HOF_HAS_VARIABLE_TEMPLATES 110namespace result_detail { 111template<class Result> 112struct result_f 113{ 114 template<class F> 115 constexpr result_adaptor<Result, F> operator()(F f) const 116 { 117 return result_adaptor<Result, F>(boost::hof::move(f)); 118 } 119}; 120 121} 122 123template<class Result> 124static constexpr auto result = result_detail::result_f<Result>{}; 125#else 126template<class Result, class F> 127constexpr result_adaptor<Result, F> result(F f) 128{ 129 return result_adaptor<Result, F>(boost::hof::move(f)); 130} 131#endif 132 133}} // namespace boost::hof 134 135#endif 136