]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/hana/include/boost/hana/fwd/integral_constant.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / fwd / integral_constant.hpp
CommitLineData
7c673cae
FG
1/*!
2@file
3Forward declares `boost::hana::integral_constant`.
4
5@copyright Louis Dionne 2013-2016
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_FWD_INTEGRAL_CONSTANT_HPP
11#define BOOST_HANA_FWD_INTEGRAL_CONSTANT_HPP
12
13#include <boost/hana/config.hpp>
14#include <boost/hana/detail/operators/adl.hpp>
15
16#include <cstddef>
17#include <type_traits>
18
19
20BOOST_HANA_NAMESPACE_BEGIN
21 //! Tag representing `hana::integral_constant`.
22 //! @relates hana::integral_constant
23 template <typename T>
24 struct integral_constant_tag {
25 using value_type = T;
26 };
27
28 namespace ic_detail {
29 template <typename T, T v>
30 struct with_index_t {
31 template <typename F>
32 constexpr void operator()(F&& f) const;
33 };
34
35 template <typename T, T v>
36 struct times_t {
37 static constexpr with_index_t<T, v> with_index{};
38
39 template <typename F>
40 constexpr void operator()(F&& f) const;
41 };
42 }
43
44 //! @ingroup group-datatypes
45 //! Compile-time value of an integral type.
46 //!
47 //! An `integral_constant` is an object that represents a compile-time
48 //! integral value. As the name suggests, `hana::integral_constant` is
49 //! basically equivalent to `std::integral_constant`, except that
50 //! `hana::integral_constant` also provide other goodies to make them
51 //! easier to use, like arithmetic operators and similar features. In
52 //! particular, `hana::integral_constant` is guaranteed to inherit from
53 //! the corresponding `std::integral_constant`, and hence have the same
54 //! members and capabilities. The sections below explain the extensions
55 //! to `std::integral_constant` provided by `hana::integral_constant`.
56 //!
57 //!
58 //! Arithmetic operators
59 //! --------------------
60 //! `hana::integral_constant` provides arithmetic operators that return
61 //! `hana::integral_constant`s to ease writing compile-time arithmetic:
62 //! @snippet example/integral_constant.cpp operators
63 //!
64 //! It is pretty important to realize that these operators return other
65 //! `integral_constant`s, not normal values of an integral type.
66 //! Actually, all those operators work pretty much in the same way.
67 //! Simply put, for an operator `@`,
68 //! @code
69 //! integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}
70 //! @endcode
71 //!
72 //! The fact that the operators return `Constant`s is very important
73 //! because it allows all the information that's known at compile-time
74 //! to be conserved as long as it's only used with other values known at
75 //! compile-time. It is also interesting to observe that whenever an
76 //! `integral_constant` is combined with a normal runtime value, the
77 //! result will be a runtime value (because of the implicit conversion).
78 //! In general, this gives us the following table
79 //!
80 //! left operand | right operand | result
81 //! :-----------------: | :-----------------: | :-----------------:
82 //! `integral_constant` | `integral_constant` | `integral_constant`
83 //! `integral_constant` | runtime | runtime
84 //! runtime | `integral_constant` | runtime
85 //! runtime | runtime | runtime
86 //!
87 //! The full range of provided operators is
88 //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
89 //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
90 //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
91 //! - %Logical: `||`, `&&`, `!`
92 //!
93 //!
94 //! Construction with user-defined literals
95 //! ---------------------------------------
96 //! `integral_constant`s of type `long long` can be created with the
97 //! `_c` user-defined literal, which is contained in the `literals`
98 //! namespace:
99 //! @snippet example/integral_constant.cpp literals
100 //!
101 //!
102 //! Modeled concepts
103 //! ----------------
104 //! 1. `Constant` and `IntegralConstant`\n
105 //! An `integral_constant` is a model of the `IntegralConstant` concept in
106 //! the most obvious way possible. Specifically,
107 //! @code
108 //! integral_constant<T, v>::value == v // of type T
109 //! @endcode
110 //! The model of `Constant` follows naturally from the model of `IntegralConstant`, i.e.
111 //! @code
112 //! value<integral_constant<T, v>>() == v // of type T
113 //! @endcode
114 //!
115 //! 2. `Comparable`, `Orderable`, `Logical`, `Monoid`, `Group`, `Ring`, and `EuclideanRing`, `Hashable`\n
116 //! Those models are exactly those provided for `Constant`s, which are
117 //! documented in their respective concepts.
118#ifdef BOOST_HANA_DOXYGEN_INVOKED
119 template <typename T, T v>
120 struct integral_constant {
121 //! Call a function n times.
122 //!
123 //! `times` allows a nullary function to be invoked `n` times:
124 //! @code
125 //! int_<3>::times(f)
126 //! @endcode
127 //! should be expanded by any decent compiler to
128 //! @code
129 //! f(); f(); f();
130 //! @endcode
131 //!
132 //! This can be useful in several contexts, e.g. for loop unrolling:
133 //! @snippet example/integral_constant.cpp times_loop_unrolling
134 //!
135 //! Note that `times` is really a static function object, not just a
136 //! static function. This allows `int_<n>::%times` to be passed to
137 //! higher-order algorithms:
138 //! @snippet example/integral_constant.cpp times_higher_order
139 //!
140 //! Also, since static members can be accessed using both the `.` and
141 //! the `::` syntax, one can take advantage of this (loophole?) to
142 //! call `times` on objects just as well as on types:
143 //! @snippet example/integral_constant.cpp from_object
144 //!
145 //! @note
146 //! `times` is equivalent to the `hana::repeat` function, which works
147 //! on an arbitrary `IntegralConstant`.
148 //!
149 //! Sometimes, it is also useful to know the index we're at inside the
150 //! function. This can be achieved by using `times.with_index`:
151 //! @snippet example/integral_constant.cpp times_with_index_runtime
152 //!
153 //! Remember that `times` is a _function object_, and hence it can
154 //! have subobjects. `with_index` is just a function object nested
155 //! inside `times`, which allows for this nice little interface. Also
156 //! note that the indices passed to the function are `integral_constant`s;
157 //! they are known at compile-time. Hence, we can do compile-time stuff
158 //! with them, like indexing inside a tuple:
159 //! @snippet example/integral_constant.cpp times_with_index_compile_time
160 //!
161 //! @note
162 //! `times.with_index(f)` guarantees that the calls to `f` will be
163 //! done in order of ascending index. In other words, `f` will be
164 //! called as `f(0)`, `f(1)`, `f(2)`, etc., but with `integral_constant`s
165 //! instead of normal integers. Side effects can also be done in the
166 //! function passed to `times` and `times.with_index`.
167 template <typename F>
168 static constexpr void times(F&& f) {
169 f(); f(); ... f(); // n times total
170 }
171
172 //! Equivalent to `hana::plus`
173 template <typename X, typename Y>
174 friend constexpr auto operator+(X&& x, Y&& y);
175
176 //! Equivalent to `hana::minus`
177 template <typename X, typename Y>
178 friend constexpr auto operator-(X&& x, Y&& y);
179
180 //! Equivalent to `hana::negate`
181 template <typename X>
182 friend constexpr auto operator-(X&& x);
183
184 //! Equivalent to `hana::mult`
185 template <typename X, typename Y>
186 friend constexpr auto operator*(X&& x, Y&& y);
187
188 //! Equivalent to `hana::div`
189 template <typename X, typename Y>
190 friend constexpr auto operator/(X&& x, Y&& y);
191
192 //! Equivalent to `hana::mod`
193 template <typename X, typename Y>
194 friend constexpr auto operator%(X&& x, Y&& y);
195
196 //! Equivalent to `hana::equal`
197 template <typename X, typename Y>
198 friend constexpr auto operator==(X&& x, Y&& y);
199
200 //! Equivalent to `hana::not_equal`
201 template <typename X, typename Y>
202 friend constexpr auto operator!=(X&& x, Y&& y);
203
204 //! Equivalent to `hana::or_`
205 template <typename X, typename Y>
206 friend constexpr auto operator||(X&& x, Y&& y);
207
208 //! Equivalent to `hana::and_`
209 template <typename X, typename Y>
210 friend constexpr auto operator&&(X&& x, Y&& y);
211
212 //! Equivalent to `hana::not_`
213 template <typename X>
214 friend constexpr auto operator!(X&& x);
215
216 //! Equivalent to `hana::less`
217 template <typename X, typename Y>
218 friend constexpr auto operator<(X&& x, Y&& y);
219
220 //! Equivalent to `hana::greater`
221 template <typename X, typename Y>
222 friend constexpr auto operator>(X&& x, Y&& y);
223
224 //! Equivalent to `hana::less_equal`
225 template <typename X, typename Y>
226 friend constexpr auto operator<=(X&& x, Y&& y);
227
228 //! Equivalent to `hana::greater_equal`
229 template <typename X, typename Y>
230 friend constexpr auto operator>=(X&& x, Y&& y);
231 };
232#else
233 template <typename T, T v>
234 struct integral_constant
235 : std::integral_constant<T, v>
236 , detail::operators::adl<integral_constant<T, v>>
237 {
238 using type = integral_constant; // override std::integral_constant::type
239 static constexpr ic_detail::times_t<T, v> times{};
240 using hana_tag = integral_constant_tag<T>;
241 };
242#endif
243
244 //! Creates an `integral_constant` holding the given compile-time value.
245 //! @relates hana::integral_constant
246 //!
247 //! Specifically, `integral_c<T, v>` is a `hana::integral_constant`
248 //! holding the compile-time value `v` of an integral type `T`.
249 //!
250 //!
251 //! @tparam T
252 //! The type of the value to hold in the `integral_constant`.
253 //! It must be an integral type.
254 //!
255 //! @tparam v
256 //! The integral value to hold in the `integral_constant`.
257 //!
258 //!
259 //! Example
260 //! -------
261 //! @snippet example/integral_constant.cpp integral_c
262 template <typename T, T v>
263 constexpr integral_constant<T, v> integral_c{};
264
265
266 //! @relates hana::integral_constant
267 template <bool b>
268 using bool_ = integral_constant<bool, b>;
269
270 //! @relates hana::integral_constant
271 template <bool b>
272 constexpr bool_<b> bool_c{};
273
274 //! @relates hana::integral_constant
275 using true_ = bool_<true>;
276
277 //! @relates hana::integral_constant
278 constexpr auto true_c = bool_c<true>;
279
280 //! @relates hana::integral_constant
281 using false_ = bool_<false>;
282
283 //! @relates hana::integral_constant
284 constexpr auto false_c = bool_c<false>;
285
286
287 //! @relates hana::integral_constant
288 template <char c>
289 using char_ = integral_constant<char, c>;
290
291 //! @relates hana::integral_constant
292 template <char c>
293 constexpr char_<c> char_c{};
294
295
296 //! @relates hana::integral_constant
297 template <short i>
298 using short_ = integral_constant<short, i>;
299
300 //! @relates hana::integral_constant
301 template <short i>
302 constexpr short_<i> short_c{};
303
304
305 //! @relates hana::integral_constant
306 template <unsigned short i>
307 using ushort_ = integral_constant<unsigned short, i>;
308
309 //! @relates hana::integral_constant
310 template <unsigned short i>
311 constexpr ushort_<i> ushort_c{};
312
313
314 //! @relates hana::integral_constant
315 template <int i>
316 using int_ = integral_constant<int, i>;
317
318 //! @relates hana::integral_constant
319 template <int i>
320 constexpr int_<i> int_c{};
321
322
323 //! @relates hana::integral_constant
324 template <unsigned int i>
325 using uint = integral_constant<unsigned int, i>;
326
327 //! @relates hana::integral_constant
328 template <unsigned int i>
329 constexpr uint<i> uint_c{};
330
331
332 //! @relates hana::integral_constant
333 template <long i>
334 using long_ = integral_constant<long, i>;
335
336 //! @relates hana::integral_constant
337 template <long i>
338 constexpr long_<i> long_c{};
339
340
341 //! @relates hana::integral_constant
342 template <unsigned long i>
343 using ulong = integral_constant<unsigned long, i>;
344
345 //! @relates hana::integral_constant
346 template <unsigned long i>
347 constexpr ulong<i> ulong_c{};
348
349
350 //! @relates hana::integral_constant
351 template <long long i>
352 using llong = integral_constant<long long, i>;
353
354 //! @relates hana::integral_constant
355 template <long long i>
356 constexpr llong<i> llong_c{};
357
358
359 //! @relates hana::integral_constant
360 template <unsigned long long i>
361 using ullong = integral_constant<unsigned long long, i>;
362
363 //! @relates hana::integral_constant
364 template <unsigned long long i>
365 constexpr ullong<i> ullong_c{};
366
367
368 //! @relates hana::integral_constant
369 template <std::size_t i>
370 using size_t = integral_constant<std::size_t, i>;
371
372 //! @relates hana::integral_constant
373 template <std::size_t i>
374 constexpr size_t<i> size_c{};
375
376
377 namespace literals {
378 //! Creates a `hana::integral_constant` from a literal.
379 //! @relatesalso boost::hana::integral_constant
380 //!
381 //! The literal is parsed at compile-time and the result is returned
382 //! as a `llong<...>`.
383 //!
384 //! @note
385 //! We use `llong<...>` instead of `ullong<...>` because using an
386 //! unsigned type leads to unexpected behavior when doing stuff like
387 //! `-1_c`. If we used an unsigned type, `-1_c` would be something
388 //! like `ullong<-1>` which is actually `ullong<something huge>`.
389 //!
390 //!
391 //! Example
392 //! -------
393 //! @snippet example/integral_constant.cpp literals
394 template <char ...c>
395 constexpr auto operator"" _c();
396 }
397BOOST_HANA_NAMESPACE_END
398
399#endif // !BOOST_HANA_FWD_INTEGRAL_CONSTANT_HPP