1 /*=============================================================================
2 Copyright (c) 2016 Paul Fultz II
3 limit.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_LIMIT_H
9 #define BOOST_HOF_GUARD_LIMIT_H
10
11 /// limit
12 /// =====
13 ///
14 /// Description
15 /// -----------
16 ///
17 /// The `limit` function decorator annotates the function with the max number
18 /// of parameters. The `limit_c` version can be used to give the max number
19 /// directly(instead of relying on an integral constant). The parameter limit
20 /// can be read by using the [`function_param_limit`](function_param_limit)
21 /// trait. Using `limit` is useful to improve error reporting with partially
22 /// evaluated functions.
23 ///
24 /// Synopsis
25 /// --------
26 ///
27 /// template<class IntegralConstant>
28 /// constexpr auto limit(IntegralConstant);
29 ///
30 /// template<std::size_t N, class F>
31 /// constexpr auto limit_c(F);
32 ///
33 /// Requirements
34 /// ------------
35 ///
36 /// IntegralConstant must be:
37 ///
38 /// * IntegralConstant
39 ///
40 /// F must be:
41 ///
42 /// * [ConstInvocable](ConstInvocable)
43 /// * MoveConstructible
44 ///
45 /// Example
46 /// -------
47 ///
48 /// #include <boost/hof.hpp>
49 /// #include <cassert>
50 /// using namespace boost::hof;
51 ///
52 /// struct sum_f
53 /// {
54 /// template<class T>
55 /// int operator()(T x, T y) const
56 /// {
57 /// return x+y;
58 /// }
59 /// };
60 /// BOOST_HOF_STATIC_FUNCTION(sum) = limit_c<2>(sum_f());
61 ///
62 /// int main() {
63 /// assert(3 == sum(1, 2));
64 /// }
65 ///
66 /// See Also
67 /// --------
68 ///
69 /// * [Partial function evaluation](<Partial function evaluation>)
70 /// * [function_param_limit](function_param_limit)
71 ///
72
73 #include <boost/hof/detail/callable_base.hpp>
74 #include <boost/hof/detail/forward.hpp>
75 #include <boost/hof/detail/delegate.hpp>
76 #include <boost/hof/detail/move.hpp>
77 #include <boost/hof/detail/static_const_var.hpp>
78 #include <boost/hof/always.hpp>
79 #include <boost/hof/function_param_limit.hpp>
80
81 namespace boost { namespace hof {
82
83 namespace detail {
84 // TODO: Make this work with fit_rewritable1_tag
85 template<std::size_t N, class F>
86 struct limit_adaptor : detail::callable_base<F>
87 {
88 typedef std::integral_constant<std::size_t, N> fit_function_param_limit;
BOOST_HOF_INHERIT_CONSTRUCTORboost::hof::detail::limit_adaptor89 BOOST_HOF_INHERIT_CONSTRUCTOR(limit_adaptor, detail::callable_base<F>)
90
91 template<class... Ts>
92 constexpr const detail::callable_base<F>& base_function(Ts&&... xs) const
93 {
94 return boost::hof::always_ref(*this)(xs...);
95 }
96
97 BOOST_HOF_RETURNS_CLASS(limit_adaptor);
98
99 template<class... Ts, class=typename std::enable_if<(sizeof...(Ts) <= N)>::type>
100 constexpr BOOST_HOF_SFINAE_RESULT(const detail::callable_base<F>&, id_<Ts>...)
101 operator()(Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
102 (
103 (BOOST_HOF_MANGLE_CAST(const detail::callable_base<F>&)(BOOST_HOF_CONST_THIS->base_function(xs...)))
104 (BOOST_HOF_FORWARD(Ts)(xs)...)
105 );
106
107 };
108
109 template<std::size_t N>
110 struct make_limit_f
111 {
make_limit_fboost::hof::detail::make_limit_f112 constexpr make_limit_f()
113 {}
114 template<class F>
operator ()boost::hof::detail::make_limit_f115 constexpr limit_adaptor<N, F> operator()(F f) const
116 {
117 return limit_adaptor<N, F>(static_cast<F&&>(f));
118 }
119 };
120
121 struct limit_f
122 {
123 template<class IntegralConstant, std::size_t N=IntegralConstant::type::value>
operator ()boost::hof::detail::limit_f124 constexpr make_limit_f<N> operator()(IntegralConstant) const
125 {
126 return {};
127 }
128 };
129
130 }
131
132 template<std::size_t N, class F>
limit_c(F f)133 constexpr detail::limit_adaptor<N, F> limit_c(F f)
134 {
135 return detail::limit_adaptor<N, F>(static_cast<F&&>(f));
136 }
137
138 BOOST_HOF_DECLARE_STATIC_VAR(limit, detail::limit_f);
139
140 }} // namespace boost::hof
141
142 #endif
143