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::Logical`.
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_LOGICAL_HPP
0011 #define BOOST_HANA_FWD_CONCEPT_LOGICAL_HPP
0012 
0013 #include <boost/hana/config.hpp>
0014 
0015 
0016 namespace boost { namespace hana {
0017     //! @ingroup group-concepts
0018     //! @defgroup group-Logical Logical
0019     //! The `Logical` concept represents types with a truth value.
0020     //!
0021     //! Intuitively, a `Logical` is just a `bool`, or something that can act
0022     //! like one. However, in the context of programming with heterogeneous
0023     //! objects, it becomes extremely important to distinguish between those
0024     //! objects whose truth value is known at compile-time, and those whose
0025     //! truth value is only known at runtime. The reason why this is so
0026     //! important is because it is possible to branch at compile-time on
0027     //! a condition whose truth value is known at compile-time, and hence
0028     //! the return type of the enclosing function can depend on that truth
0029     //! value. However, if the truth value is only known at runtime, then
0030     //! the compiler has to compile both branches (because any or both of
0031     //! them may end up being used), which creates the additional requirement
0032     //! that both branches must evaluate to the same type.
0033     //!
0034     //! More specifically, `Logical` (almost) represents a [boolean algebra][1],
0035     //! which is a mathematical structure encoding the usual properties that
0036     //! allow us to reason with `bool`. The exact properties that must be
0037     //! satisfied by any model of `Logical` are rigorously stated in the laws
0038     //! below.
0039     //!
0040     //!
0041     //! Truth, falsity and logical equivalence
0042     //! --------------------------------------
0043     //! A `Logical` `x` is said to be _true-valued_, or sometimes also just
0044     //! _true_ as an abuse of notation, if
0045     //! @code
0046     //!     if_(x, true, false) == true
0047     //! @endcode
0048     //!
0049     //! Similarly, `x` is _false-valued_, or sometimes just _false_, if
0050     //! @code
0051     //!     if_(x, true, false) == false
0052     //! @endcode
0053     //!
0054     //! This provides a standard way of converting any `Logical` to a straight
0055     //! `bool`. The notion of truth value suggests another definition, which
0056     //! is that of logical equivalence. We will say that two `Logical`s `x`
0057     //! and `y` are _logically equivalent_ if they have the same truth value.
0058     //! To denote that some expressions `p` and `q` of a Logical data type are
0059     //! logically equivalent, we will sometimes also write
0060     //! @code
0061     //!     p   if and only if   q
0062     //! @endcode
0063     //! which is very common in mathematics. The intuition behind this notation
0064     //! is that whenever `p` is true-valued, then `q` should be; but when `p`
0065     //! is false-valued, then `q` should be too. Hence, `p` should be
0066     //! true-valued when (and only when) `q` is true-valued.
0067     //!
0068     //!
0069     //! Minimal complete definition
0070     //! ---------------------------
0071     //! `eval_if`, `not_` and `while_`
0072     //!
0073     //! All the other functions can be defined in those terms:
0074     //! @code
0075     //!     if_(cond, x, y) = eval_if(cond, lazy(x), lazy(y))
0076     //!     and_(x, y) = if_(x, y, x)
0077     //!     or_(x, y) = if_(x, x, y)
0078     //!     etc...
0079     //! @endcode
0080     //!
0081     //!
0082     //! Laws
0083     //! ----
0084     //! As outlined above, the `Logical` concept almost represents a boolean
0085     //! algebra. The rationale for this laxity is to allow things like integers
0086     //! to act like `Logical`s, which is aligned with C++, even though they do
0087     //! not form a boolean algebra. Even though we depart from the usual
0088     //! axiomatization of boolean algebras, we have found through experience
0089     //! that the definition of a Logical given here is largely compatible with
0090     //! intuition.
0091     //!
0092     //! The following laws must be satisfied for any data type `L` modeling
0093     //! the `Logical` concept. Let `a`, `b` and `c` be objects of a `Logical`
0094     //! data type, and let `t` and `f` be arbitrary _true-valued_ and
0095     //! _false-valued_ `Logical`s of that data type, respectively. Then,
0096     //! @code
0097     //!     // associativity
0098     //!     or_(a, or_(b, c))   == or_(or_(a, b), c)
0099     //!     and_(a, and_(b, c)) == and_(and_(a, b), c)
0100     //!
0101     //!     // equivalence through commutativity
0102     //!     or_(a, b)   if and only if   or_(b, a)
0103     //!     and_(a, b)  if and only if   and_(b, a)
0104     //!
0105     //!     // absorption
0106     //!     or_(a, and_(a, b)) == a
0107     //!     and_(a, or_(a, b)) == a
0108     //!
0109     //!     // left identity
0110     //!     or_(a, f)  == a
0111     //!     and_(a, t) == a
0112     //!
0113     //!     // distributivity
0114     //!     or_(a, and_(b, c)) == and_(or_(a, b), or_(a, c))
0115     //!     and_(a, or_(b, c)) == or_(and_(a, b), and_(a, c))
0116     //!
0117     //!     // complements
0118     //!     or_(a, not_(a))  is true-valued
0119     //!     and_(a, not_(a)) is false-valued
0120     //! @endcode
0121     //!
0122     //! > #### Why is the above not a boolean algebra?
0123     //! > If you look closely, you will find that we depart from the usual
0124     //! > boolean algebras because:
0125     //! > 1. we do not require the elements representing truth and falsity to
0126     //! >    be unique
0127     //! > 2. we do not enforce commutativity of the `and_` and `or_` operations
0128     //! > 3. because we do not enforce commutativity, the identity laws become
0129     //! >    left-identity laws
0130     //!
0131     //!
0132     //! Concrete models
0133     //! ---------------
0134     //! `hana::integral_constant`
0135     //!
0136     //!
0137     //! Free model for arithmetic data types
0138     //! ------------------------------------
0139     //! A data type `T` is arithmetic if `std::is_arithmetic<T>::%value` is
0140     //! true. For an arithmetic data type `T`, a model of `Logical` is
0141     //! provided automatically by using the result of the builtin implicit
0142     //! conversion to `bool` as a truth value. Specifically, the minimal
0143     //! complete definition for those data types is
0144     //! @code
0145     //!     eval_if(cond, then, else_) = cond ? then(id) : else(id)
0146     //!     not_(cond) = static_cast<T>(cond ? false : true)
0147     //!     while_(pred, state, f) = equivalent to a normal while loop
0148     //! @endcode
0149     //!
0150     //! > #### Rationale for not providing a model for all contextually convertible to bool data types
0151     //! > The `not_` method can not be implemented in a meaningful way for all
0152     //! > of those types. For example, one can not cast a pointer type `T*`
0153     //! > to bool and then back again to `T*` in a meaningful way. With an
0154     //! > arithmetic type `T`, however, it is possible to cast from `T` to
0155     //! > bool and then to `T` again; the result will be `0` or `1` depending
0156     //! > on the truth value. If you want to use a pointer type or something
0157     //! > similar in a conditional, it is suggested to explicitly convert it
0158     //! > to bool by using `to<bool>`.
0159     //!
0160     //!
0161     //! [1]: http://en.wikipedia.org/wiki/Boolean_algebra_(structure)
0162     template <typename L>
0163     struct Logical;
0164 }} // end namespace boost::hana
0165 
0166 #endif // !BOOST_HANA_FWD_CONCEPT_LOGICAL_HPP