1/*=============================================================================
2 Copyright (c) 2015 Paul Fultz II
3 repeat_while.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_REPEAT_WHILE_H
9#define BOOST_HOF_GUARD_REPEAT_WHILE_H
10
11/// repeat_while
12/// ======
13///
14/// Description
15/// -----------
16///
17/// The `repeat_while` function decorator will repeatedly apply a function while
18/// the predicate returns a boolean that is true. If the predicate returns an
19/// `IntergralConstant` then the predicate is only evaluated at compile-time.
20///
21///
22/// Synopsis
23/// --------
24///
25/// template<class Predicate>
26/// constexpr auto repeat_while(Predicate predicate);
27///
28/// Requirements
29/// ------------
30///
31/// Predicate must be:
32///
33/// * [ConstFunctionObject](ConstFunctionObject)
34/// * MoveConstructible
35///
36/// Example
37/// -------
38///
39/// #include <boost/hof.hpp>
40/// #include <cassert>
41///
42/// struct increment
43/// {
44/// template<class T>
45/// constexpr std::integral_constant<int, T::value + 1> operator()(T) const
46/// {
47/// return std::integral_constant<int, T::value + 1>();
48/// }
49/// };
50///
51/// struct not_6
52/// {
53/// template<class T>
54/// constexpr std::integral_constant<bool, (T::value != 6)>
55/// operator()(T) const
56/// {
57/// return std::integral_constant<bool, (T::value != 6)>();
58/// }
59/// };
60///
61/// typedef std::integral_constant<int, 1> one;
62/// typedef std::integral_constant<int, 6> six;
63///
64/// int main() {
65/// auto increment_until_6 = boost::hof::repeat_while(not_6())(increment());
66/// static_assert(std::is_same<six, decltype(increment_until_6(one()))>::value, "Error");
67/// }
68///
69
70#include <boost/hof/always.hpp>
71#include <boost/hof/detail/delegate.hpp>
72#include <boost/hof/detail/result_of.hpp>
73#include <boost/hof/detail/move.hpp>
74#include <boost/hof/decorate.hpp>
75#include <boost/hof/detail/static_const_var.hpp>
76#include <boost/hof/first_of.hpp>
77#include <boost/hof/detail/recursive_constexpr_depth.hpp>
78
79namespace boost { namespace hof { namespace detail {
80
81template<class P, class... Ts>
82struct compute_predicate
83{
84 typedef decltype(std::declval<P>()(std::declval<Ts>()...)) type;
85};
86
87template<bool B>
88struct while_repeater
89{
90 template<class F, class P, class... Ts>
91 constexpr BOOST_HOF_SFINAE_RESULT(while_repeater<
92 compute_predicate<P, typename result_of<const F&, id_<Ts>...>::type>::type::value
93 >, id_<const F&>, id_<const P&>, result_of<const F&, id_<Ts>...>)
94 operator()(const F& f, const P& p, Ts&&... xs) const BOOST_HOF_SFINAE_RETURNS
95 (
96 while_repeater<
97 compute_predicate<P, decltype(f(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
98 >()(f, p, f(BOOST_HOF_FORWARD(Ts)(xs)...))
99 );
100};
101
102template<>
103struct while_repeater<false>
104{
105 template<class F, class P, class T>
106 constexpr T operator()(const F&, const P&, T&& x) const
107 BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT(x)
108 {
109 return x;
110 }
111};
112
113struct repeat_while_constant_decorator
114{
115 template<class P, class F, class... Ts>
116 constexpr auto operator()(const P& p, const F& f, Ts&&... xs) const BOOST_HOF_RETURNS
117 (
118 detail::while_repeater<
119 detail::compute_predicate<P, decltype(std::declval<F>()(BOOST_HOF_FORWARD(Ts)(xs)...))>::type::value
120 >()
121 (
122 f,
123 p,
124 BOOST_HOF_FORWARD(Ts)(xs)...
125 )
126 );
127};
128
129template<int Depth>
130struct repeat_while_integral_decorator
131{
132 template<class P, class F, class T, class... Ts, class Self=repeat_while_integral_decorator<Depth-1>>
133 constexpr auto operator()(const P& p, const F& f, T&& x, Ts&&... xs) const BOOST_HOF_RETURNS
134 (
135 (p(x, BOOST_HOF_FORWARD(Ts)(xs)...)) ?
136 Self()(
137 p,
138 f,
139 f(x, BOOST_HOF_FORWARD(Ts)(xs)...)
140 ) :
141 BOOST_HOF_FORWARD(T)(x)
142 );
143};
144
145template<>
146struct repeat_while_integral_decorator<0>
147{
148 template<class P, class F, class T, class Self=repeat_while_integral_decorator<0>>
149#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
150 constexpr
151#endif
152 auto operator()(const P& p, const F& f, T x) const
153 BOOST_HOF_RETURNS_DEDUCE_NOEXCEPT((p(x), f(x)))
154 -> decltype(f(x))
155 {
156 while(p(x))
157 {
158 // TODO: Should move?
159 x = f(x);
160 }
161 return x;
162 }
163};
164}
165
166#if BOOST_HOF_HAS_RELAXED_CONSTEXPR
167#define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH 1
168#else
169#define BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH BOOST_HOF_RECURSIVE_CONSTEXPR_DEPTH
170#endif
171
172BOOST_HOF_DECLARE_STATIC_VAR(repeat_while, decorate_adaptor<
173 boost::hof::first_of_adaptor<
174 detail::repeat_while_constant_decorator,
175 detail::repeat_while_integral_decorator<BOOST_HOF_REPEAT_WHILE_CONSTEXPR_DEPTH>
176 >
177>);
178
179}} // namespace boost::hof
180
181#endif
182

source code of boost/libs/hof/include/boost/hof/repeat_while.hpp