/*============================================================================= Copyright (c) 2014 Paul Fultz II result.h Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ==============================================================================*/ #ifndef BOOST_HOF_GUARD_RESULT_H #define BOOST_HOF_GUARD_RESULT_H /// result /// ====== /// /// Description /// ----------- /// /// The `result` function adaptor sets the return type for the function, which /// can be useful when dealing with multiple overloads. Since the return type /// is no longer dependent on the parameters passed to the function, the /// `result_adaptor` provides a nested `result_type` that is the return type /// of the function. /// /// Synopsis /// -------- /// /// template /// constexpr result_adaptor result(F f); /// /// Requirements /// ------------ /// /// F must be: /// /// * [ConstInvocable](ConstInvocable) /// * MoveConstructible /// /// Example /// ------- /// /// #include /// #include /// /// struct id /// { /// template /// T operator()(T x) const /// { /// return x; /// } /// }; /// /// int main() { /// auto int_result = boost::hof::result(id()); /// static_assert(std::is_same::value, "Not the same type"); /// } /// #include #include #include #include namespace boost { namespace hof { template struct result_adaptor : detail::callable_base { BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base) typedef Result result_type; struct failure : failure_for> {}; template constexpr const detail::callable_base& base_function(Ts&&... xs) const { return boost::hof::always_ref(*this)(xs...); } template::value)>::type> constexpr result_type operator()(Ts&&... xs) const { return this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...); }; }; template struct result_adaptor : detail::callable_base { BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base) typedef void result_type; template constexpr const detail::callable_base& base_function(Ts&&... xs) const { return boost::hof::always_ref(*this)(xs...); } template::value)>::type> constexpr typename detail::holder::type operator()(Ts&&... xs) const { return (typename detail::holder::type)this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...); }; }; #if BOOST_HOF_HAS_VARIABLE_TEMPLATES namespace result_detail { template struct result_f { template constexpr result_adaptor operator()(F f) const { return result_adaptor(boost::hof::move(f)); } }; } template static constexpr auto result = result_detail::result_f{}; #else template constexpr result_adaptor result(F f) { return result_adaptor(boost::hof::move(f)); } #endif }} // namespace boost::hof #endif