3 Defines the barebones `boost::hana::integral_constant` template, but no
6 @copyright Louis Dionne 2013-2017
7 Distributed under the Boost Software License, Version 1.0.
8 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
11 #ifndef BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
12 #define BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
14 #include <boost/hana/config.hpp>
15 #include <boost/hana/detail/operators/adl.hpp>
17 #include <type_traits>
20 namespace boost { namespace hana {
21 //! Tag representing `hana::integral_constant`.
22 //! @relates hana::integral_constant
24 struct integral_constant_tag {
29 template <typename T, T v>
32 constexpr void operator()(F&& f) const;
35 template <typename T, T v>
37 static constexpr with_index_t<T, v> with_index{};
40 constexpr void operator()(F&& f) const;
44 //! @ingroup group-datatypes
45 //! Compile-time value of an integral type.
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`.
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
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 `@`,
69 //! integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}
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
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
87 //! The full range of provided operators is
88 //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
89 //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
90 //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
91 //! - %Logical: `||`, `&&`, `!`
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`
99 //! @snippet example/integral_constant.cpp literals
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,
108 //! integral_constant<T, v>::value == v // of type T
110 //! The model of `Constant` follows naturally from the model of `IntegralConstant`, i.e.
112 //! value<integral_constant<T, v>>() == v // of type T
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.
123 //! `times` allows a nullary function to be invoked `n` times:
125 //! int_<3>::times(f)
127 //! should be expanded by any decent compiler to
132 //! This can be useful in several contexts, e.g. for loop unrolling:
133 //! @snippet example/integral_constant.cpp times_loop_unrolling
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
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
146 //! `times` is equivalent to the `hana::repeat` function, which works
147 //! on an arbitrary `IntegralConstant`.
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
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
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
172 //! Equivalent to `hana::plus`
173 template <typename X, typename Y>
174 friend constexpr auto operator+(X&& x, Y&& y);
176 //! Equivalent to `hana::minus`
177 template <typename X, typename Y>
178 friend constexpr auto operator-(X&& x, Y&& y);
180 //! Equivalent to `hana::negate`
181 template <typename X>
182 friend constexpr auto operator-(X&& x);
184 //! Equivalent to `hana::mult`
185 template <typename X, typename Y>
186 friend constexpr auto operator*(X&& x, Y&& y);
188 //! Equivalent to `hana::div`
189 template <typename X, typename Y>
190 friend constexpr auto operator/(X&& x, Y&& y);
192 //! Equivalent to `hana::mod`
193 template <typename X, typename Y>
194 friend constexpr auto operator%(X&& x, Y&& y);
196 //! Equivalent to `hana::equal`
197 template <typename X, typename Y>
198 friend constexpr auto operator==(X&& x, Y&& y);
200 //! Equivalent to `hana::not_equal`
201 template <typename X, typename Y>
202 friend constexpr auto operator!=(X&& x, Y&& y);
204 //! Equivalent to `hana::or_`
205 template <typename X, typename Y>
206 friend constexpr auto operator||(X&& x, Y&& y);
208 //! Equivalent to `hana::and_`
209 template <typename X, typename Y>
210 friend constexpr auto operator&&(X&& x, Y&& y);
212 //! Equivalent to `hana::not_`
213 template <typename X>
214 friend constexpr auto operator!(X&& x);
216 //! Equivalent to `hana::less`
217 template <typename X, typename Y>
218 friend constexpr auto operator<(X&& x, Y&& y);
220 //! Equivalent to `hana::greater`
221 template <typename X, typename Y>
222 friend constexpr auto operator>(X&& x, Y&& y);
224 //! Equivalent to `hana::less_equal`
225 template <typename X, typename Y>
226 friend constexpr auto operator<=(X&& x, Y&& y);
228 //! Equivalent to `hana::greater_equal`
229 template <typename X, typename Y>
230 friend constexpr auto operator>=(X&& x, Y&& y);
233 template <typename T, T v>
234 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
235 struct __declspec(empty_bases) integral_constant
237 struct integral_constant
239 : std::integral_constant<T, v>
240 , detail::operators::adl<integral_constant<T, v>>
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>;
247 }} // end namespace boost::hana
249 #endif // !BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP