summaryrefslogtreecommitdiff
path: root/boost/hof/result.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/hof/result.hpp')
-rw-r--r--boost/hof/result.hpp135
1 files changed, 135 insertions, 0 deletions
diff --git a/boost/hof/result.hpp b/boost/hof/result.hpp
new file mode 100644
index 0000000000..e2c1d93dae
--- /dev/null
+++ b/boost/hof/result.hpp
@@ -0,0 +1,135 @@
+/*=============================================================================
+ 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<class Result, class F>
+/// constexpr result_adaptor<Result, F> result(F f);
+///
+/// Requirements
+/// ------------
+///
+/// F must be:
+///
+/// * [ConstInvocable](ConstInvocable)
+/// * MoveConstructible
+///
+/// Example
+/// -------
+///
+/// #include <boost/hof.hpp>
+/// #include <cassert>
+///
+/// struct id
+/// {
+/// template<class T>
+/// T operator()(T x) const
+/// {
+/// return x;
+/// }
+/// };
+///
+/// int main() {
+/// auto int_result = boost::hof::result<int>(id());
+/// static_assert(std::is_same<decltype(int_result(true)), int>::value, "Not the same type");
+/// }
+///
+
+#include <boost/hof/detail/callable_base.hpp>
+#include <boost/hof/is_invocable.hpp>
+#include <boost/hof/always.hpp>
+#include <boost/hof/reveal.hpp>
+
+namespace boost { namespace hof {
+
+template<class Result, class F>
+struct result_adaptor : detail::callable_base<F>
+{
+ BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
+
+ typedef Result result_type;
+
+ struct failure
+ : failure_for<detail::callable_base<F>>
+ {};
+
+ template<class... Ts>
+ constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
+ {
+ return boost::hof::always_ref(*this)(xs...);
+ }
+
+ template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type>
+ constexpr result_type operator()(Ts&&... xs) const
+ {
+ return this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...);
+ };
+};
+
+template<class F>
+struct result_adaptor<void, F> : detail::callable_base<F>
+{
+ BOOST_HOF_INHERIT_CONSTRUCTOR(result_adaptor, detail::callable_base<F>)
+
+ typedef void result_type;
+
+ template<class... Ts>
+ constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
+ {
+ return boost::hof::always_ref(*this)(xs...);
+ }
+
+ template<class... Ts, class=typename std::enable_if<(boost::hof::is_invocable<F, Ts...>::value)>::type>
+ constexpr typename detail::holder<Ts...>::type operator()(Ts&&... xs) const
+ {
+ return (typename detail::holder<Ts...>::type)this->base_function(xs...)(BOOST_HOF_FORWARD(Ts)(xs)...);
+ };
+};
+
+#if BOOST_HOF_HAS_VARIABLE_TEMPLATES
+namespace result_detail {
+template<class Result>
+struct result_f
+{
+ template<class F>
+ constexpr result_adaptor<Result, F> operator()(F f) const
+ {
+ return result_adaptor<Result, F>(boost::hof::move(f));
+ }
+};
+
+}
+
+template<class Result>
+static constexpr auto result = result_detail::result_f<Result>{};
+#else
+template<class Result, class F>
+constexpr result_adaptor<Result, F> result(F f)
+{
+ return result_adaptor<Result, F>(boost::hof::move(f));
+}
+#endif
+
+}} // namespace boost::hof
+
+#endif