Back to home page

EIC code displayed by LXR

 
 

    


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