]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/hana/detail/integral_constant.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / hana / detail / integral_constant.hpp
CommitLineData
7c673cae
FG
1/*!
2@file
b32b8144
FG
3Defines the barebones `boost::hana::integral_constant` template, but no
4operations on it.
7c673cae 5
b32b8144 6@copyright Louis Dionne 2013-2017
7c673cae
FG
7Distributed under the Boost Software License, Version 1.0.
8(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
9 */
10
b32b8144
FG
11#ifndef BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
12#define BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
7c673cae
FG
13
14#include <boost/hana/config.hpp>
15#include <boost/hana/detail/operators/adl.hpp>
16
7c673cae
FG
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>
92f5a8d4
TL
234#ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
235 struct __declspec(empty_bases) integral_constant
236#else
7c673cae 237 struct integral_constant
92f5a8d4 238#endif
7c673cae
FG
239 : std::integral_constant<T, v>
240 , detail::operators::adl<integral_constant<T, v>>
241 {
242 using type = integral_constant; // override std::integral_constant::type
243 static constexpr ic_detail::times_t<T, v> times{};
244 using hana_tag = integral_constant_tag<T>;
245 };
246#endif
7c673cae
FG
247BOOST_HANA_NAMESPACE_END
248
b32b8144 249#endif // !BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP