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