1/*!
2@file
3Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
4
5Copyright Louis Dionne 2013-2022
6Distributed 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
34namespace boost { namespace hana {
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 =
161 starts_with_zero && (arr[1] == 'x' || arr[1] == 'X');
162 bool is_binary = starts_with_zero && arr[1] == 'b';
163
164 if (is_hex) {
165 //0xDEADBEEF (hexadecimal)
166 base = 16;
167 offset = 2;
168 }
169 else if (is_binary) {
170 //0b101011101 (binary)
171 base = 2;
172 offset = 2;
173 }
174 else if (starts_with_zero) {
175 //012345 (octal)
176 base = 8;
177 offset = 1;
178 }
179 }
180
181 long long number = 0;
182 long long multiplier = 1;
183
184 for (std::size_t i = 0; i < N - offset; ++i) {
185 char c = arr[N - 1 - i];
186 if (c != '\'') { // skip digit separators
187 number += to_int(c) * multiplier;
188 multiplier *= base;
189 }
190 }
191
192 return number;
193 }
194 }
195
196 namespace literals {
197 template <char ...c>
198 constexpr auto operator"" _c() {
199 return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
200 }
201 }
202
203 //////////////////////////////////////////////////////////////////////////
204 // Model of Constant/IntegralConstant
205 //////////////////////////////////////////////////////////////////////////
206 template <typename T>
207 struct IntegralConstant<integral_constant_tag<T>> {
208 static constexpr bool value = true;
209 };
210
211 template <typename T, typename C>
212 struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
213 : embedding<is_embedded<typename C::value_type, T>::value>
214 {
215 template <typename N>
216 static constexpr auto apply(N const&)
217 { return integral_constant<T, N::value>{}; }
218 };
219
220 //////////////////////////////////////////////////////////////////////////
221 // Optimizations
222 //////////////////////////////////////////////////////////////////////////
223 template <typename T>
224 struct eval_if_impl<integral_constant_tag<T>> {
225 template <typename Cond, typename Then, typename Else>
226 static constexpr decltype(auto)
227 apply(Cond const&, Then&& t, Else&& e) {
228 constexpr bool cond = static_cast<bool>(Cond::value);
229 return eval_if_impl::apply(hana::bool_<cond>{},
230 static_cast<Then&&>(t),
231 static_cast<Else&&>(e));
232 }
233
234 template <typename Then, typename Else>
235 static constexpr decltype(auto)
236 apply(hana::true_ const&, Then&& t, Else&&)
237 { return hana::eval(static_cast<Then&&>(t)); }
238
239 template <typename Then, typename Else>
240 static constexpr decltype(auto)
241 apply(hana::false_ const&, Then&&, Else&& e)
242 { return hana::eval(static_cast<Else&&>(e)); }
243 };
244
245 template <typename T>
246 struct if_impl<integral_constant_tag<T>> {
247 template <typename Cond, typename Then, typename Else>
248 static constexpr decltype(auto)
249 apply(Cond const&, Then&& t, Else&& e) {
250 constexpr bool cond = static_cast<bool>(Cond::value);
251 return if_impl::apply(hana::bool_<cond>{},
252 static_cast<Then&&>(t),
253 static_cast<Else&&>(e));
254 }
255
256 //! @todo We could return `Then` instead of `auto` to sometimes save
257 //! a copy, but that would break some code that would return a
258 //! reference to a `type` object. I think the code that would be
259 //! broken should be changed, but more thought needs to be given.
260 template <typename Then, typename Else>
261 static constexpr auto
262 apply(hana::true_ const&, Then&& t, Else&&)
263 { return static_cast<Then&&>(t); }
264
265 template <typename Then, typename Else>
266 static constexpr auto
267 apply(hana::false_ const&, Then&&, Else&& e)
268 { return static_cast<Else&&>(e); }
269 };
270}} // end namespace boost::hana
271
272#endif // !BOOST_HANA_BOOL_HPP
273

source code of boost/libs/hana/include/boost/hana/bool.hpp