• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
with_indexic_detail::go48             static constexpr void with_index(F&& f)
49             { (void)swallow{T{}, ((void)f(integral_constant<T, i>{}), i)...}; }
50 
51             template <typename F>
without_indexic_detail::go52             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>
operator ()(F && f) const58         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>
operator ()(F && f) const63         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 
to_int(char c)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>
parse(const char (& arr)[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                 if (c != '\'') { // skip digit separators
186                     number += to_int(c) * multiplier;
187                     multiplier *= base;
188                 }
189             }
190 
191             return number;
192         }
193     }
194 
195     namespace literals {
196         template <char ...c>
operator ""_c()197         constexpr auto operator"" _c() {
198             return hana::llong<ic_detail::parse<sizeof...(c)>({c...})>{};
199         }
200     }
201 
202     //////////////////////////////////////////////////////////////////////////
203     // Model of Constant/IntegralConstant
204     //////////////////////////////////////////////////////////////////////////
205     template <typename T>
206     struct IntegralConstant<integral_constant_tag<T>> {
207         static constexpr bool value = true;
208     };
209 
210     template <typename T, typename C>
211     struct to_impl<integral_constant_tag<T>, C, when<hana::IntegralConstant<C>::value>>
212         : embedding<is_embedded<typename C::value_type, T>::value>
213     {
214         template <typename N>
applyto_impl215         static constexpr auto apply(N const&)
216         { return integral_constant<T, N::value>{}; }
217     };
218 
219     //////////////////////////////////////////////////////////////////////////
220     // Optimizations
221     //////////////////////////////////////////////////////////////////////////
222     template <typename T>
223     struct eval_if_impl<integral_constant_tag<T>> {
224         template <typename Cond, typename Then, typename Else>
225         static constexpr decltype(auto)
applyeval_if_impl226         apply(Cond const&, Then&& t, Else&& e) {
227             constexpr bool cond = static_cast<bool>(Cond::value);
228             return eval_if_impl::apply(hana::bool_<cond>{},
229                                        static_cast<Then&&>(t),
230                                        static_cast<Else&&>(e));
231         }
232 
233         template <typename Then, typename Else>
234         static constexpr decltype(auto)
applyeval_if_impl235         apply(hana::true_ const&, Then&& t, Else&&)
236         { return hana::eval(static_cast<Then&&>(t)); }
237 
238         template <typename Then, typename Else>
239         static constexpr decltype(auto)
applyeval_if_impl240         apply(hana::false_ const&, Then&&, Else&& e)
241         { return hana::eval(static_cast<Else&&>(e)); }
242     };
243 
244     template <typename T>
245     struct if_impl<integral_constant_tag<T>> {
246         template <typename Cond, typename Then, typename Else>
247         static constexpr decltype(auto)
applyif_impl248         apply(Cond const&, Then&& t, Else&& e) {
249             constexpr bool cond = static_cast<bool>(Cond::value);
250             return if_impl::apply(hana::bool_<cond>{},
251                                   static_cast<Then&&>(t),
252                                   static_cast<Else&&>(e));
253         }
254 
255         //! @todo We could return `Then` instead of `auto` to sometimes save
256         //! a copy, but that would break some code that would return a
257         //! reference to a `type` object. I think the code that would be
258         //! broken should be changed, but more thought needs to be given.
259         template <typename Then, typename Else>
260         static constexpr auto
applyif_impl261         apply(hana::true_ const&, Then&& t, Else&&)
262         { return static_cast<Then&&>(t); }
263 
264         template <typename Then, typename Else>
265         static constexpr auto
applyif_impl266         apply(hana::false_ const&, Then&&, Else&& e)
267         { return static_cast<Else&&>(e); }
268     };
269 BOOST_HANA_NAMESPACE_END
270 
271 #endif // !BOOST_HANA_BOOL_HPP
272