3 Defines `boost::hana::while_`.
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
10 #ifndef BOOST_HANA_WHILE_HPP
11 #define BOOST_HANA_WHILE_HPP
13 #include <boost/hana/fwd/while.hpp>
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/concept/constant.hpp>
17 #include <boost/hana/concept/constant.hpp>
18 #include <boost/hana/concept/logical.hpp>
19 #include <boost/hana/config.hpp>
20 #include <boost/hana/core/to.hpp>
21 #include <boost/hana/core/dispatch.hpp>
22 #include <boost/hana/detail/canonical_constant.hpp>
24 #include <type_traits>
27 BOOST_HANA_NAMESPACE_BEGIN
29 template <typename Pred, typename State, typename F>
30 constexpr decltype(auto) while_t::operator()(Pred&& pred, State&& state, F&& f) const {
31 using Cond = decltype(pred(state));
32 using Bool = typename hana::tag_of<Cond>::type;
33 using While = BOOST_HANA_DISPATCH_IF(while_impl<Bool>,
34 hana::Logical<Bool>::value
37 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
38 static_assert(hana::Logical<Bool>::value,
39 "hana::while_(pred, state, f) requires 'pred(state)' to be a Logical");
42 return While::apply(static_cast<Pred&&>(pred),
43 static_cast<State&&>(state),
48 template <typename L, bool condition>
49 struct while_impl<L, hana::when<condition>> : hana::default_ {
50 template <typename ...Args>
51 static constexpr auto apply(Args&& ...) = delete;
55 struct while_impl<L, hana::when<std::is_arithmetic<L>::value>> {
56 template <typename Pred, typename State, typename F>
57 static auto apply(Pred&& pred, State&& state, F&& f)
59 true ? f(static_cast<State&&>(state))
60 : static_cast<State&&>(state)
64 decltype(auto) r = f(static_cast<State&&>(state));
65 return hana::while_(static_cast<Pred&&>(pred),
66 static_cast<decltype(r)&&>(r),
70 return static_cast<State&&>(state);
76 struct while_impl<C, hana::when<
77 hana::Constant<C>::value &&
78 hana::Logical<typename C::value_type>::value
80 template <typename Pred, typename State, typename F>
81 static constexpr State
82 while_helper(hana::false_, Pred&&, State&& state, F&&) {
83 return static_cast<State&&>(state);
86 template <typename Pred, typename State, typename F>
87 static constexpr decltype(auto)
88 while_helper(hana::true_, Pred&& pred, State&& state, F&& f) {
89 decltype(auto) r = f(static_cast<State&&>(state));
90 return hana::while_(static_cast<Pred&&>(pred),
91 static_cast<decltype(r)&&>(r),
95 template <typename Pred, typename State, typename F>
96 static constexpr decltype(auto)
97 apply(Pred&& pred, State&& state, F&& f) {
98 // Since `pred(state)` returns a `Constant`, we do not actually
99 // need to call it; we only need its decltype. However, we still
100 // call it to run potential side effects. I'm not sure whether
101 // that is desirable, since we pretty much take for granted that
102 // functions are pure, but we'll do it like this for now. Also, I
103 // think there is something rather deep hidden behind this, and
104 // understanding what must be done here should give us a better
105 // understanding of something non-trivial.
106 auto cond_ = pred(state);
107 constexpr auto cond = hana::value(cond_);
108 constexpr bool truth_value = hana::if_(cond, true, false);
109 return while_helper(hana::bool_c<truth_value>,
110 static_cast<Pred&&>(pred),
111 static_cast<State&&>(state),
112 static_cast<F&&>(f));
115 BOOST_HANA_NAMESPACE_END
117 #endif // !BOOST_HANA_WHILE_HPP