1 /*!
2 @file
3 Defines `boost::hana::eval_if`.
4 
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)
8  */
9 
10 #ifndef BOOST_HANA_EVAL_IF_HPP
11 #define BOOST_HANA_EVAL_IF_HPP
12 
13 #include <boost/hana/fwd/eval_if.hpp>
14 
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/concept/constant.hpp>
17 #include <boost/hana/concept/logical.hpp>
18 #include <boost/hana/config.hpp>
19 #include <boost/hana/core/dispatch.hpp>
20 #include <boost/hana/eval.hpp>
21 #include <boost/hana/if.hpp>
22 
23 #include <type_traits>
24 
25 
26 BOOST_HANA_NAMESPACE_BEGIN
27     //! @cond
28     template <typename Cond, typename Then, typename Else>
operator ()(Cond && cond,Then && then_,Else && else_) const29     constexpr decltype(auto) eval_if_t::operator()(Cond&& cond, Then&& then_, Else&& else_) const {
30         using Bool = typename hana::tag_of<Cond>::type;
31         using EvalIf = BOOST_HANA_DISPATCH_IF(eval_if_impl<Bool>,
32             hana::Logical<Bool>::value
33         );
34 
35     #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
36         static_assert(hana::Logical<Bool>::value,
37         "hana::eval_if(cond, then, else) requires 'cond' to be a Logical");
38     #endif
39 
40         return EvalIf::apply(static_cast<Cond&&>(cond),
41                              static_cast<Then&&>(then_),
42                              static_cast<Else&&>(else_));
43     }
44     //! @endcond
45 
46     template <typename L, bool condition>
47     struct eval_if_impl<L, when<condition>> : default_ {
48         template <typename ...Args>
49         static constexpr auto apply(Args&& ...) = delete;
50     };
51 
52     //////////////////////////////////////////////////////////////////////////
53     // Model for arithmetic data types
54     //////////////////////////////////////////////////////////////////////////
55     template <typename L>
56     struct eval_if_impl<L, when<std::is_arithmetic<L>::value>> {
57         template <typename Cond, typename T, typename E>
applyeval_if_impl58         static constexpr auto apply(Cond const& cond, T&& t, E&& e) {
59             return cond ? hana::eval(static_cast<T&&>(t))
60                         : hana::eval(static_cast<E&&>(e));
61         }
62     };
63 
64     //////////////////////////////////////////////////////////////////////////
65     // Model for Constants over a Logical
66     //////////////////////////////////////////////////////////////////////////
67     template <typename C>
68     struct eval_if_impl<C, when<
69         hana::Constant<C>::value &&
70         Logical<typename C::value_type>::value
71     >> {
72         template <typename Then, typename Else>
73         static constexpr decltype(auto)
eval_if_helpereval_if_impl74         eval_if_helper(hana::true_, Then&& t, Else&&)
75         { return hana::eval(static_cast<Then&&>(t)); }
76 
77         template <typename Then, typename Else>
78         static constexpr decltype(auto)
eval_if_helpereval_if_impl79         eval_if_helper(hana::false_, Then&&, Else&& e)
80         { return hana::eval(static_cast<Else&&>(e)); }
81 
82         template <typename Cond, typename Then, typename Else>
applyeval_if_impl83         static constexpr decltype(auto) apply(Cond const&, Then&& t, Else&& e) {
84             constexpr auto cond = hana::value<Cond>();
85             constexpr bool truth_value = hana::if_(cond, true, false);
86             return eval_if_helper(hana::bool_<truth_value>{},
87                                   static_cast<Then&&>(t),
88                                   static_cast<Else&&>(e));
89         }
90     };
91 BOOST_HANA_NAMESPACE_END
92 
93 #endif // !BOOST_HANA_EVAL_IF_HPP
94