|
||||
File indexing completed on 2025-01-18 09:37:58
0001 /*! 0002 @file 0003 Forward declares `boost::hana::Constant`. 0004 0005 Copyright Louis Dionne 2013-2022 0006 Distributed under the Boost Software License, Version 1.0. 0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 0008 */ 0009 0010 #ifndef BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP 0011 #define BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP 0012 0013 #include <boost/hana/config.hpp> 0014 0015 0016 namespace boost { namespace hana { 0017 //! @ingroup group-concepts 0018 //! @defgroup group-Constant Constant 0019 //! The `Constant` concept represents data that can be manipulated at 0020 //! compile-time. 0021 //! 0022 //! At its core, `Constant` is simply a generalization of the principle 0023 //! behind `std::integral_constant` to all types that can be constructed 0024 //! at compile-time, i.e. to all types with a `constexpr` constructor 0025 //! (also called [Literal types][1]). More specifically, a `Constant` is 0026 //! an object from which a `constexpr` value may be obtained (through the 0027 //! `value` method) regardless of the `constexpr`ness of the object itself. 0028 //! 0029 //! All `Constant`s must be somewhat equivalent, in the following sense. 0030 //! Let `C(T)` and `D(U)` denote the tags of `Constant`s holding objects 0031 //! of type `T` and `U`, respectively. Then, an object with tag `D(U)` 0032 //! must be convertible to an object with tag `C(T)` whenever `U` is 0033 //! convertible to `T`, as determined by `is_convertible`. The 0034 //! interpretation here is that a `Constant` is just a box holding 0035 //! an object of some type, and it should be possible to swap between 0036 //! boxes whenever the objects inside the boxes can be swapped. 0037 //! 0038 //! Because of this last requirement, one could be tempted to think that 0039 //! specialized "boxes" like `std::integral_constant` are prevented from 0040 //! being `Constant`s because they are not able to hold objects of any 0041 //! type `T` (`std::integral_constant` may only hold integral types). 0042 //! This is false; the requirement should be interpreted as saying that 0043 //! whenever `C(T)` is _meaningful_ (e.g. only when `T` is integral for 0044 //! `std::integral_constant`) _and_ there exists a conversion from `U` 0045 //! to `T`, then a conversion from `D(U)` to `C(T)` should also exist. 0046 //! The precise requirements for being a `Constant` are embodied in the 0047 //! following laws. 0048 //! 0049 //! 0050 //! Minimal complete definition 0051 //! --------------------------- 0052 //! `value` and `to`, satisfying the laws below. 0053 //! 0054 //! 0055 //! Laws 0056 //! ---- 0057 //! Let `c` be an object of with tag `C`, which represents a `Constant` 0058 //! holding an object with tag `T`. The first law ensures that the value 0059 //! of the wrapped object is always a constant expression by requiring 0060 //! the following to be well-formed: 0061 //! @code 0062 //! constexpr auto x = hana::value<decltype(c)>(); 0063 //! @endcode 0064 //! 0065 //! This means that the `value` function must return an object that can 0066 //! be constructed at compile-time. It is important to note how `value` 0067 //! only receives the type of the object and not the object itself. 0068 //! This is the core of the `Constant` concept; it means that the only 0069 //! information required to implement `value` must be stored in the _type_ 0070 //! of its argument, and hence be available statically. 0071 //! 0072 //! The second law that must be satisfied ensures that `Constant`s are 0073 //! basically dumb boxes, which makes it possible to provide models for 0074 //! many concepts without much work from the user. The law simply asks 0075 //! for the following expression to be valid: 0076 //! @code 0077 //! to<C>(i) 0078 //! @endcode 0079 //! where, `i` is an _arbitrary_ `Constant` holding an internal value 0080 //! with a tag that can be converted to `T`, as determined by the 0081 //! `hana::is_convertible` metafunction. In other words, whenever `U` is 0082 //! convertible to `T`, a `Constant` holding a `U` is convertible to 0083 //! a `Constant` holding a `T`, if such a `Constant` can be created. 0084 //! 0085 //! Finally, the tag `C` must provide a nested `value_type` alias to `T`, 0086 //! which allows us to query the tag of the inner value held by objects 0087 //! with tag `C`. In other words, the following must be true for any 0088 //! object `c` with tag `C`: 0089 //! @code 0090 //! std::is_same< 0091 //! C::value_type, 0092 //! tag_of<decltype(hana::value(c))>::type 0093 //! >::value 0094 //! @endcode 0095 //! 0096 //! 0097 //! Refined concepts 0098 //! ---------------- 0099 //! In certain cases, a `Constant` can automatically be made a model of 0100 //! another concept. In particular, if a `Constant` `C` is holding an 0101 //! object of tag `T`, and if `T` models a concept `X`, then `C` may 0102 //! in most cases model `X` by simply performing whatever operation is 0103 //! required on its underlying value, and then wrapping the result back 0104 //! in a `C`. 0105 //! 0106 //! More specifically, if a `Constant` `C` has an underlying value 0107 //! (`C::value_type`) which is a model of `Comparable`, `Orderable`, 0108 //! `Logical`, or `Monoid` up to `EuclideanRing`, then `C` must also 0109 //! be a model of those concepts. In other words, when `C::value_type` 0110 //! models one of the listed concepts, `C` itself must also model that 0111 //! concept. However, note that free models are provided for all of 0112 //! those concepts, so no additional work must be done. 0113 //! 0114 //! While it would be possible in theory to provide models for concepts 0115 //! like `Foldable` too, only a couple of concepts are useful to have as 0116 //! `Constant` in practice. Providing free models for the concepts listed 0117 //! above is useful because it allows various types of integral constants 0118 //! (`std::integral_constant`, `mpl::integral_c`, etc...) to easily have 0119 //! models for them just by defining the `Constant` concept. 0120 //! 0121 //! @remark 0122 //! An interesting observation is that `Constant` is actually the 0123 //! canonical embedding of the subcategory of `constexpr` things 0124 //! into the Hana category, which contains everything in this library. 0125 //! Hence, whatever is true in that subcategory is also true here, via 0126 //! this functor. This is why we can provide models of any concept that 0127 //! works on `constexpr` things for Constants, by simply passing them 0128 //! through that embedding. 0129 //! 0130 //! 0131 //! Concrete models 0132 //! --------------- 0133 //! `hana::integral_constant` 0134 //! 0135 //! 0136 //! Provided conversion to the tag of the underlying value 0137 //! ------------------------------------------------------ 0138 //! Any `Constant` `c` holding an underlying value of tag `T` is 0139 //! convertible to any tag `U` such that `T` is convertible to `U`. 0140 //! Specifically, the conversion is equivalent to 0141 //! @code 0142 //! to<U>(c) == to<U>(value<decltype(c)>()) 0143 //! @endcode 0144 //! 0145 //! Also, those conversions are marked as an embedding whenever the 0146 //! conversion of underlying types is an embedding. This is to allow 0147 //! Constants to inter-operate with `constexpr` objects easily: 0148 //! @code 0149 //! plus(int_c<1>, 1) == 2 0150 //! @endcode 0151 //! 0152 //! Strictly speaking, __this is sometimes a violation__ of what it means 0153 //! to be an embedding. Indeed, while there exists an embedding from any 0154 //! Constant to a `constexpr` object (since Constant is just the canonical 0155 //! inclusion), there is no embedding from a Constant to a runtime 0156 //! object since we would lose the ability to define the `value` method 0157 //! (the `constexpr`ness of the object would have been lost). Since there 0158 //! is no way to distinguish `constexpr` and non-`constexpr` objects based 0159 //! on their type, Hana has no way to know whether the conversion is to a 0160 //! `constexpr` object of not. In other words, the `to` method has no way 0161 //! to differentiate between 0162 //! @code 0163 //! constexpr int i = hana::to<int>(int_c<1>); 0164 //! @endcode 0165 //! which is an embedding, and 0166 //! @code 0167 //! int i = hana::to<int>(int_c<1>); 0168 //! @endcode 0169 //! 0170 //! which isn't. To be on the safer side, we could mark the conversion 0171 //! as not-an-embedding. However, if e.g. the conversion from 0172 //! `integral_constant_tag<int>` to `int` was not marked as an embedding, 0173 //! we would have to write `plus(to<int>(int_c<1>), 1)` instead of just 0174 //! `plus(int_c<1>, 1)`, which is cumbersome. Hence, the conversion is 0175 //! marked as an embedding, but this also means that code like 0176 //! @code 0177 //! int i = 1; 0178 //! plus(int_c<1>, i); 0179 //! @endcode 0180 //! will be considered valid, which implicitly loses the fact that 0181 //! `int_c<1>` is a Constant, and hence does not follow the usual rules 0182 //! for cross-type operations in Hana. 0183 //! 0184 //! 0185 //! Provided common data type 0186 //! ------------------------- 0187 //! Because of the requirement that `Constant`s be interchangeable when 0188 //! their contents are compatible, two `Constant`s `A` and `B` will have 0189 //! a common data type whenever `A::value_type` and `B::value_type` have 0190 //! one. Their common data type is an unspecified `Constant` `C` such 0191 //! that `C::value_type` is exactly `common_t<A::value_type, B::value_type>`. 0192 //! A specialization of the `common` metafunction is provided for 0193 //! `Constant`s to reflect this. 0194 //! 0195 //! In the same vein, a common data type is also provided from any 0196 //! constant `A` to a type `T` such that `A::value_type` and `T` share 0197 //! a common type. The common type between `A` and `T` is obviously the 0198 //! common type between `A::value_type` and `T`. As explained above in 0199 //! the section on conversions, this is sometimes a violation of the 0200 //! definition of a common type, because there must be an embedding 0201 //! to the common type, which is not always the case. For the same 0202 //! reasons as explained above, this common type is still provided. 0203 //! 0204 //! 0205 //! [1]: http://en.cppreference.com/w/cpp/named_req/LiteralType 0206 template <typename C> 0207 struct Constant; 0208 }} // end namespace boost::hana 0209 0210 #endif // !BOOST_HANA_FWD_CONCEPT_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 |