Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / hana / bool.hpp
1 /*!
2 @file
3 Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
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_BOOL_HPP
11 #define BOOST_HANA_BOOL_HPP
12
13 #include <boost/hana/fwd/bool.hpp>
14
15 #include <boost/hana/concept/integral_constant.hpp>
16 #include <boost/hana/config.hpp>
17 #include <boost/hana/core/to.hpp>
18 #include <boost/hana/core/when.hpp>
19 #include <boost/hana/detail/operators/arithmetic.hpp>
20 #include <boost/hana/detail/operators/comparable.hpp>
21 #include <boost/hana/detail/operators/logical.hpp>
22 #include <boost/hana/detail/operators/orderable.hpp>
23 #include <boost/hana/eval.hpp>
24 #include <boost/hana/fwd/core/tag_of.hpp>
25 #include <boost/hana/fwd/eval_if.hpp>
26 #include <boost/hana/fwd/if.hpp>
27 #include <boost/hana/fwd/value.hpp>
28
29 #include <cstddef>
30 #include <type_traits>
31 #include <utility>
32
33
34 BOOST_HANA_NAMESPACE_BEGIN
35     //////////////////////////////////////////////////////////////////////////
36     // integral_constant
37     //////////////////////////////////////////////////////////////////////////
38     //! @cond
39     namespace ic_detail {
40         template <typename T, T N, typename = std::make_integer_sequence<T, N>>
41         struct go;
42
43         template <typename T, T N, T ...i>
44         struct go<T, N, std::integer_sequence<T, i...>> {
45             using swallow = T[];
46
47             template <typename F>
48             static constexpr void with_index(F&& f)
49             { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
50
51             template <typename F>
52             static constexpr void without_index(F&& f)
53             { (void)swallow{T{}, ((void)f(), i)...}; }
54         };
55
56         template <typename T, T v>
57         template <typename F>
58         constexpr void with_index_t<T, v>::operator()(F&& f) const
59         { go<T, ((void)sizeof(&f), v)>::with_index(static_cast<F&&>(f)); }
60
61         template <typename T, T v>
62         template <typename F>
63         constexpr void times_t<T, v>::operator()(F&& f) const
64         { go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); }
65
66         // avoid link-time error
67         template <typename T, T v>
68         constexpr with_index_t<T, v> times_t<T, v>::with_index;
69     }
70
71     // avoid link-time error
72     template <typename T, T v>
73     constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times;
74
75     template <typename T, T v>
76     struct tag_of<integral_constant<T, v>> {
77         using type = integral_constant_tag<T>;
78     };
79     //! @endcond
80
81     //////////////////////////////////////////////////////////////////////////
82     // Operators
83     //////////////////////////////////////////////////////////////////////////
84     namespace detail {
85         template <typename T>
86         struct comparable_operators<integral_constant_tag<T>> {
87             static constexpr bool value = true;
88         };
89         template <typename T>
90         struct orderable_operators<integral_constant_tag<T>> {
91             static constexpr bool value = true;
92         };
93         template <typename T>
94         struct arithmetic_operators<integral_constant_tag<T>> {
95             static constexpr bool value = true;
96         };
97         template <typename T>
98         struct logical_operators<integral_constant_tag<T>> {
99             static constexpr bool value = true;
100         };
101     }
102
103 #define BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(op)                          \
104     template <typename U, U u, typename V, V v>                             \
105     constexpr integral_constant<decltype(u op v), (u op v)>                 \
106     operator op(integral_constant<U, u>, integral_constant<V, v>)           \
107     { return {}; }                                                          \
108     /**/
109
110 #define BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(op)                           \
111     template <typename U, U u>                                              \
112     constexpr integral_constant<decltype(op u), (op u)>                     \
113     operator op(integral_constant<U, u>)                                    \
114     { return {}; }                                                          \
115     /**/
116
117     // Arithmetic
118     BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)
119
120     // Bitwise
121     BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(~)
122     BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(&)
123     BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(|)
124     BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(^)
125     BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(<<)
126     BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP(>>)
127
128 #undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
129 #undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP
130
131
132     //////////////////////////////////////////////////////////////////////////
133     // User-defined literal
134     //////////////////////////////////////////////////////////////////////////
135     namespace ic_detail {
136
137         constexpr int to_int(char c) {
138             int result = 0;
139
140             if (c >= 'A' && c <= 'F') {
141                 result = static_cast<int>(c) - static_cast<int>('A') + 10;
142             }
143             else if (c >= 'a' && c <= 'f') {
144                 result = static_cast<int>(c) - static_cast<int>('a') + 10;
145             }
146             else {
147                 result = static_cast<int>(c) - static_cast<int>('0');
148             }
149
150             return result;
151         }
152
153         template<std::size_t N>
154         constexpr long long parse(const char (&arr)[N]) {
155             long long base = 10;
156             std::size_t offset = 0;
157
158             if (N > 2) {
159                 bool starts_with_zero = arr[0] == '0';
160                 bool is_hex = starts_with_zero && arr[1] == 'x';
161                 bool is_binary = starts_with_zero && arr[1] == 'b';
162
163                 if (is_hex) {
164                     //0xDEADBEEF (hexadecimal)
165                     base = 16;
166                     offset = 2;
167                 }
168                 else if (is_binary) {
169                     //0b101011101 (binary)
170                     base = 2;
171                     offset = 2;
172                 }
173                 else if (starts_with_zero) {
174                     //012345 (octal)
175                     base = 8;
176                     offset = 1;
177                 }
178             }
179
180             long long number = 0;
181             long long multiplier = 1;
182
183             for (std::size_t i = 0; i < N - offset; ++i) {
184                 char c = arr[N - 1 - i];
185                 number += to_int(c) * multiplier;
186                 multiplier *= base;
187             }
188
189             return number;
190         }
191     }
192
193     namespace literals {
194         template <char ...c>
195         constexpr auto operator"" _c() {
196             return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
197         }
198     }
199
200     //////////////////////////////////////////////////////////////////////////
201     // Model of Constant/IntegralConstant
202     //////////////////////////////////////////////////////////////////////////
203     template <typename T>
204     struct IntegralConstant<integral_constant_tag<T>> {
205         static constexpr bool value = true;
206     };
207
208     template <typename T, typename C>
209     struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
210         : embedding<is_embedded<typename C::value_type, T>::value>
211     {
212         template <typename N>
213         static constexpr auto apply(N const&)
214         { return integral_constant<T, N::value>{}; }
215     };
216
217     //////////////////////////////////////////////////////////////////////////
218     // Optimizations
219     //////////////////////////////////////////////////////////////////////////
220     template <typename T>
221     struct eval_if_impl<integral_constant_tag<T>> {
222         template <typename Cond, typename Then, typename Else>
223         static constexpr decltype(auto)
224         apply(Cond const&, Then&& t, Else&& e) {
225             constexpr bool cond = static_cast<bool>(Cond::value);
226             return eval_if_impl::apply(hana::bool_<cond>{},
227                                        static_cast<Then&&>(t),
228                                        static_cast<Else&&>(e));
229         }
230
231         template <typename Then, typename Else>
232         static constexpr decltype(auto)
233         apply(hana::true_ const&, Then&& t, Else&&)
234         { return hana::eval(static_cast<Then&&>(t)); }
235
236         template <typename Then, typename Else>
237         static constexpr decltype(auto)
238         apply(hana::false_ const&, Then&&, Else&& e)
239         { return hana::eval(static_cast<Else&&>(e)); }
240     };
241
242     template <typename T>
243     struct if_impl<integral_constant_tag<T>> {
244         template <typename Cond, typename Then, typename Else>
245         static constexpr decltype(auto)
246         apply(Cond const&, Then&& t, Else&& e) {
247             constexpr bool cond = static_cast<bool>(Cond::value);
248             return if_impl::apply(hana::bool_<cond>{},
249                                   static_cast<Then&&>(t),
250                                   static_cast<Else&&>(e));
251         }
252
253         //! @todo We could return `Then` instead of `auto` to sometimes save
254         //! a copy, but that would break some code that would return a
255         //! reference to a `type` object. I think the code that would be
256         //! broken should be changed, but more thought needs to be given.
257         template <typename Then, typename Else>
258         static constexpr auto
259         apply(hana::true_ const&, Then&& t, Else&&)
260         { return static_cast<Then&&>(t); }
261
262         template <typename Then, typename Else>
263         static constexpr auto
264         apply(hana::false_ const&, Then&&, Else&& e)
265         { return static_cast<Else&&>(e); }
266     };
267 BOOST_HANA_NAMESPACE_END
268
269 #endif // !BOOST_HANA_BOOL_HPP