Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 09:52:46

0001 /*!
0002 @file
0003 Defines the barebones `boost::hana::integral_constant` template, but no
0004 operations on it.
0005 
0006 Copyright Louis Dionne 2013-2022
0007 Distributed under the Boost Software License, Version 1.0.
0008 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
0009  */
0010 
0011 #ifndef BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
0012 #define BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP
0013 
0014 #include <boost/hana/config.hpp>
0015 #include <boost/hana/detail/operators/adl.hpp>
0016 
0017 #include <type_traits>
0018 
0019 
0020 namespace boost { namespace hana {
0021     //! Tag representing `hana::integral_constant`.
0022     //! @relates hana::integral_constant
0023     template <typename T>
0024     struct integral_constant_tag {
0025         using value_type = T;
0026     };
0027 
0028     namespace ic_detail {
0029         template <typename T, T v>
0030         struct with_index_t {
0031             template <typename F>
0032             constexpr void operator()(F&& f) const;
0033         };
0034 
0035         template <typename T, T v>
0036         struct times_t {
0037             static constexpr with_index_t<T, v> with_index{};
0038 
0039             template <typename F>
0040             constexpr void operator()(F&& f) const;
0041         };
0042     }
0043 
0044     //! @ingroup group-datatypes
0045     //! Compile-time value of an integral type.
0046     //!
0047     //! An `integral_constant` is an object that represents a compile-time
0048     //! integral value. As the name suggests, `hana::integral_constant` is
0049     //! basically equivalent to `std::integral_constant`, except that
0050     //! `hana::integral_constant` also provide other goodies to make them
0051     //! easier to use, like arithmetic operators and similar features. In
0052     //! particular, `hana::integral_constant` is guaranteed to inherit from
0053     //! the corresponding `std::integral_constant`, and hence have the same
0054     //! members and capabilities. The sections below explain the extensions
0055     //! to `std::integral_constant` provided by `hana::integral_constant`.
0056     //!
0057     //!
0058     //! Arithmetic operators
0059     //! --------------------
0060     //! `hana::integral_constant` provides arithmetic operators that return
0061     //! `hana::integral_constant`s to ease writing compile-time arithmetic:
0062     //! @snippet example/integral_constant.cpp operators
0063     //!
0064     //! It is pretty important to realize that these operators return other
0065     //! `integral_constant`s, not normal values of an integral type.
0066     //! Actually, all those operators work pretty much in the same way.
0067     //! Simply put, for an operator `@`,
0068     //! @code
0069     //!     integral_constant<T, x>{} @ integral_constant<T, y>{} == integral_constant<T, x @ y>{}
0070     //! @endcode
0071     //!
0072     //! The fact that the operators return `Constant`s is very important
0073     //! because it allows all the information that's known at compile-time
0074     //! to be conserved as long as it's only used with other values known at
0075     //! compile-time. It is also interesting to observe that whenever an
0076     //! `integral_constant` is combined with a normal runtime value, the
0077     //! result will be a runtime value (because of the implicit conversion).
0078     //! In general, this gives us the following table
0079     //!
0080     //! left operand        | right operand       | result
0081     //! :-----------------: | :-----------------: | :-----------------:
0082     //! `integral_constant` | `integral_constant` | `integral_constant`
0083     //! `integral_constant` | runtime             | runtime
0084     //! runtime             | `integral_constant` | runtime
0085     //! runtime             | runtime             | runtime
0086     //!
0087     //! The full range of provided operators is
0088     //! - Arithmetic: binary `+`, binary `-`, `/`, `*`, `%`, unary `+`, unary `-`
0089     //! - Bitwise: `~`, `&`, `|`, `^`, `<<`, `>>`
0090     //! - Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`
0091     //! - %Logical: `||`, `&&`, `!`
0092     //!
0093     //!
0094     //! Construction with user-defined literals
0095     //! ---------------------------------------
0096     //! `integral_constant`s of type `long long` can be created with the
0097     //! `_c` user-defined literal, which is contained in the `literals`
0098     //! namespace:
0099     //! @snippet example/integral_constant.cpp literals
0100     //!
0101     //!
0102     //! Modeled concepts
0103     //! ----------------
0104     //! 1. `Constant` and `IntegralConstant`\n
0105     //! An `integral_constant` is a model of the `IntegralConstant` concept in
0106     //! the most obvious way possible. Specifically,
0107     //! @code
0108     //!     integral_constant<T, v>::value == v // of type T
0109     //! @endcode
0110     //! The model of `Constant` follows naturally from the model of `IntegralConstant`, i.e.
0111     //! @code
0112     //!     value<integral_constant<T, v>>() == v // of type T
0113     //! @endcode
0114     //!
0115     //! 2. `Comparable`, `Orderable`, `Logical`, `Monoid`, `Group`, `Ring`, and `EuclideanRing`, `Hashable`\n
0116     //! Those models are exactly those provided for `Constant`s, which are
0117     //! documented in their respective concepts.
0118 #ifdef BOOST_HANA_DOXYGEN_INVOKED
0119     template <typename T, T v>
0120     struct integral_constant {
0121         //! Call a function n times.
0122         //!
0123         //! `times` allows a nullary function to be invoked `n` times:
0124         //! @code
0125         //!     int_<3>::times(f)
0126         //! @endcode
0127         //! should be expanded by any decent compiler to
0128         //! @code
0129         //!     f(); f(); f();
0130         //! @endcode
0131         //!
0132         //! This can be useful in several contexts, e.g. for loop unrolling:
0133         //! @snippet example/integral_constant.cpp times_loop_unrolling
0134         //!
0135         //! Note that `times` is really a static function object, not just a
0136         //! static function. This allows `int_<n>::%times` to be passed to
0137         //! higher-order algorithms:
0138         //! @snippet example/integral_constant.cpp times_higher_order
0139         //!
0140         //! Also, since static members can be accessed using both the `.` and
0141         //! the `::` syntax, one can take advantage of this (loophole?) to
0142         //! call `times` on objects just as well as on types:
0143         //! @snippet example/integral_constant.cpp from_object
0144         //!
0145         //! @note
0146         //! `times` is equivalent to the `hana::repeat` function, which works
0147         //! on an arbitrary `IntegralConstant`.
0148         //!
0149         //! Sometimes, it is also useful to know the index we're at inside the
0150         //! function. This can be achieved by using `times.with_index`:
0151         //! @snippet example/integral_constant.cpp times_with_index_runtime
0152         //!
0153         //! Remember that `times` is a _function object_, and hence it can
0154         //! have subobjects. `with_index` is just a function object nested
0155         //! inside `times`, which allows for this nice little interface. Also
0156         //! note that the indices passed to the function are `integral_constant`s;
0157         //! they are known at compile-time. Hence, we can do compile-time stuff
0158         //! with them, like indexing inside a tuple:
0159         //! @snippet example/integral_constant.cpp times_with_index_compile_time
0160         //!
0161         //! @note
0162         //! `times.with_index(f)` guarantees that the calls to `f` will be
0163         //! done in order of ascending index. In other words, `f` will be
0164         //! called as `f(0)`, `f(1)`, `f(2)`, etc., but with `integral_constant`s
0165         //! instead of normal integers. Side effects can also be done in the
0166         //! function passed to `times` and `times.with_index`.
0167         template <typename F>
0168         static constexpr void times(F&& f) {
0169             f(); f(); ... f(); // n times total
0170         }
0171 
0172         //! Equivalent to `hana::plus`
0173         template <typename X, typename Y>
0174         friend constexpr auto operator+(X&& x, Y&& y);
0175 
0176         //! Equivalent to `hana::minus`
0177         template <typename X, typename Y>
0178         friend constexpr auto operator-(X&& x, Y&& y);
0179 
0180         //! Equivalent to `hana::negate`
0181         template <typename X>
0182         friend constexpr auto operator-(X&& x);
0183 
0184         //! Equivalent to `hana::mult`
0185         template <typename X, typename Y>
0186         friend constexpr auto operator*(X&& x, Y&& y);
0187 
0188         //! Equivalent to `hana::div`
0189         template <typename X, typename Y>
0190         friend constexpr auto operator/(X&& x, Y&& y);
0191 
0192         //! Equivalent to `hana::mod`
0193         template <typename X, typename Y>
0194         friend constexpr auto operator%(X&& x, Y&& y);
0195 
0196         //! Equivalent to `hana::equal`
0197         template <typename X, typename Y>
0198         friend constexpr auto operator==(X&& x, Y&& y);
0199 
0200         //! Equivalent to `hana::not_equal`
0201         template <typename X, typename Y>
0202         friend constexpr auto operator!=(X&& x, Y&& y);
0203 
0204         //! Equivalent to `hana::or_`
0205         template <typename X, typename Y>
0206         friend constexpr auto operator||(X&& x, Y&& y);
0207 
0208         //! Equivalent to `hana::and_`
0209         template <typename X, typename Y>
0210         friend constexpr auto operator&&(X&& x, Y&& y);
0211 
0212         //! Equivalent to `hana::not_`
0213         template <typename X>
0214         friend constexpr auto operator!(X&& x);
0215 
0216         //! Equivalent to `hana::less`
0217         template <typename X, typename Y>
0218         friend constexpr auto operator<(X&& x, Y&& y);
0219 
0220         //! Equivalent to `hana::greater`
0221         template <typename X, typename Y>
0222         friend constexpr auto operator>(X&& x, Y&& y);
0223 
0224         //! Equivalent to `hana::less_equal`
0225         template <typename X, typename Y>
0226         friend constexpr auto operator<=(X&& x, Y&& y);
0227 
0228         //! Equivalent to `hana::greater_equal`
0229         template <typename X, typename Y>
0230         friend constexpr auto operator>=(X&& x, Y&& y);
0231     };
0232 #else
0233     template <typename T, T v>
0234 #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
0235     struct __declspec(empty_bases) integral_constant
0236 #else
0237     struct integral_constant
0238 #endif
0239         : std::integral_constant<T, v>
0240         , detail::operators::adl<integral_constant<T, v>>
0241     {
0242         using type = integral_constant; // override std::integral_constant::type
0243         static constexpr ic_detail::times_t<T, v> times{};
0244         using hana_tag = integral_constant_tag<T>;
0245     };
0246 #endif
0247 }} // end namespace boost::hana
0248 
0249 #endif // !BOOST_HANA_DETAIL_INTEGRAL_CONSTANT_HPP