|
|
|||
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
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|