• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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