3 Defines the `Logical` and `Comparable` models of `boost::hana::integral_constant`.
5 @copyright Louis Dionne 2013-2016
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_BOOL_HPP
11 #define BOOST_HANA_BOOL_HPP
13 #include <boost/hana/fwd/bool.hpp>
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>
30 #include <type_traits>
34 BOOST_HANA_NAMESPACE_BEGIN
35 //////////////////////////////////////////////////////////////////////////
37 //////////////////////////////////////////////////////////////////////////
40 template <typename T, T N, typename = std::make_integer_sequence<T, N>>
43 template <typename T, T N, T ...i>
44 struct go<T, N, std::integer_sequence<T, i...>> {
48 static constexpr void with_index(F&& f)
49 { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
52 static constexpr void without_index(F&& f)
53 { (void)swallow{T{}, ((void)f(), i)...}; }
56 template <typename T, T v>
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)); }
61 template <typename T, T v>
63 constexpr void times_t<T, v>::operator()(F&& f) const
64 { go<T, ((void)sizeof(&f), v)>::without_index(static_cast<F&&>(f)); }
66 // avoid link-time error
67 template <typename T, T v>
68 constexpr with_index_t<T, v> times_t<T, v>::with_index;
71 // avoid link-time error
72 template <typename T, T v>
73 constexpr ic_detail::times_t<T, v> integral_constant<T, v>::times;
75 template <typename T, T v>
76 struct tag_of<integral_constant<T, v>> {
77 using type = integral_constant_tag<T>;
81 //////////////////////////////////////////////////////////////////////////
83 //////////////////////////////////////////////////////////////////////////
86 struct comparable_operators<integral_constant_tag<T>> {
87 static constexpr bool value = true;
90 struct orderable_operators<integral_constant_tag<T>> {
91 static constexpr bool value = true;
94 struct arithmetic_operators<integral_constant_tag<T>> {
95 static constexpr bool value = true;
98 struct logical_operators<integral_constant_tag<T>> {
99 static constexpr bool value = true;
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>) \
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>) \
118 BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP(+)
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(>>)
128 #undef BOOST_HANA_INTEGRAL_CONSTANT_UNARY_OP
129 #undef BOOST_HANA_INTEGRAL_CONSTANT_BINARY_OP
132 //////////////////////////////////////////////////////////////////////////
133 // User-defined literal
134 //////////////////////////////////////////////////////////////////////////
135 namespace ic_detail {
137 constexpr int to_int(char c) {
140 if (c >= 'A' && c <= 'F') {
141 result = static_cast<int>(c) - static_cast<int>('A') + 10;
143 else if (c >= 'a' && c <= 'f') {
144 result = static_cast<int>(c) - static_cast<int>('a') + 10;
147 result = static_cast<int>(c) - static_cast<int>('0');
153 template<std::size_t N>
154 constexpr long long parse(const char (&arr)[N]) {
156 std::size_t offset = 0;
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';
164 //0xDEADBEEF (hexadecimal)
168 else if (is_binary) {
169 //0b101011101 (binary)
173 else if (starts_with_zero) {
180 long long number = 0;
181 long long multiplier = 1;
183 for (std::size_t i = 0; i < N - offset; ++i) {
184 char c = arr[N - 1 - i];
185 number += to_int(c) * multiplier;
195 constexpr auto operator"" _c() {
196 return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
200 //////////////////////////////////////////////////////////////////////////
201 // Model of Constant/IntegralConstant
202 //////////////////////////////////////////////////////////////////////////
203 template <typename T>
204 struct IntegralConstant<integral_constant_tag<T>> {
205 static constexpr bool value = true;
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>
212 template <typename N>
213 static constexpr auto apply(N const&)
214 { return integral_constant<T, N::value>{}; }
217 //////////////////////////////////////////////////////////////////////////
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));
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)); }
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)); }
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));
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); }
262 template <typename Then, typename Else>
263 static constexpr auto
264 apply(hana::false_ const&, Then&&, Else&& e)
265 { return static_cast<Else&&>(e); }
267 BOOST_HANA_NAMESPACE_END
269 #endif // !BOOST_HANA_BOOL_HPP