tribool.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  1. // Three-state boolean logic library
  2. // Copyright Douglas Gregor 2002-2004. Use, modification and
  3. // distribution is subject to the Boost Software License, Version
  4. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // For more information, see http://www.boost.org
  7. #ifndef BOOST_LOGIC_TRIBOOL_HPP
  8. #define BOOST_LOGIC_TRIBOOL_HPP
  9. #include <boost/logic/tribool_fwd.hpp>
  10. #include <boost/config.hpp>
  11. #include <boost/detail/workaround.hpp>
  12. #ifdef BOOST_HAS_PRAGMA_ONCE
  13. # pragma once
  14. #endif
  15. namespace boost { namespace logic {
  16. /// INTERNAL ONLY
  17. namespace detail {
  18. /**
  19. * INTERNAL ONLY
  20. *
  21. * \brief A type used only to uniquely identify the 'indeterminate'
  22. * function/keyword.
  23. */
  24. struct indeterminate_t
  25. {
  26. #if BOOST_WORKAROUND(BOOST_BORLANDC, < 0x0600)
  27. char dummy_; // BCB would use 8 bytes by default
  28. #endif
  29. };
  30. } // end namespace detail
  31. /**
  32. * INTERNAL ONLY
  33. * The type of the 'indeterminate' keyword. This has the same type as the
  34. * function 'indeterminate' so that we can recognize when the keyword is
  35. * used.
  36. */
  37. typedef bool (*indeterminate_keyword_t)(tribool, detail::indeterminate_t);
  38. /**
  39. * \brief Keyword and test function for the indeterminate tribool value
  40. *
  41. * The \c indeterminate function has a dual role. It's first role is
  42. * as a unary function that tells whether the tribool value is in the
  43. * "indeterminate" state. It's second role is as a keyword
  44. * representing the indeterminate (just like "true" and "false"
  45. * represent the true and false states). If you do not like the name
  46. * "indeterminate", and would prefer to use a different name, see the
  47. * macro \c BOOST_TRIBOOL_THIRD_STATE.
  48. *
  49. * \returns <tt>x.value == tribool::indeterminate_value</tt>
  50. * \throws nothrow
  51. */
  52. BOOST_CONSTEXPR inline bool
  53. indeterminate(tribool x,
  54. detail::indeterminate_t dummy = detail::indeterminate_t()) BOOST_NOEXCEPT;
  55. /**
  56. * \brief A 3-state boolean type.
  57. *
  58. * 3-state boolean values are either true, false, or
  59. * indeterminate.
  60. */
  61. class tribool
  62. {
  63. #if defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS )
  64. private:
  65. /// INTERNAL ONLY
  66. struct dummy {
  67. void nonnull() {};
  68. };
  69. typedef void (dummy::*safe_bool)();
  70. #endif
  71. public:
  72. /**
  73. * Construct a new 3-state boolean value with the value 'false'.
  74. *
  75. * \throws nothrow
  76. */
  77. BOOST_CONSTEXPR tribool() BOOST_NOEXCEPT : value(false_value) {}
  78. /**
  79. * Construct a new 3-state boolean value with the given boolean
  80. * value, which may be \c true or \c false.
  81. *
  82. * \throws nothrow
  83. */
  84. BOOST_CONSTEXPR tribool(bool initial_value) BOOST_NOEXCEPT : value(initial_value? true_value : false_value) {}
  85. /**
  86. * Construct a new 3-state boolean value with an indeterminate value.
  87. *
  88. * \throws nothrow
  89. */
  90. BOOST_CONSTEXPR tribool(indeterminate_keyword_t) BOOST_NOEXCEPT : value(indeterminate_value) {}
  91. /**
  92. * Use a 3-state boolean in a boolean context. Will evaluate true in a
  93. * boolean context only when the 3-state boolean is definitely true.
  94. *
  95. * \returns true if the 3-state boolean is true, false otherwise
  96. * \throws nothrow
  97. */
  98. #if !defined( BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS )
  99. BOOST_CONSTEXPR explicit operator bool () const BOOST_NOEXCEPT
  100. {
  101. return value == true_value;
  102. }
  103. #else
  104. BOOST_CONSTEXPR operator safe_bool() const BOOST_NOEXCEPT
  105. {
  106. return value == true_value? &dummy::nonnull : 0;
  107. }
  108. #endif
  109. /**
  110. * The actual stored value in this 3-state boolean, which may be false, true,
  111. * or indeterminate.
  112. */
  113. enum value_t { false_value, true_value, indeterminate_value } value;
  114. };
  115. // Check if the given tribool has an indeterminate value. Also doubles as a
  116. // keyword for the 'indeterminate' value
  117. BOOST_CONSTEXPR inline bool indeterminate(tribool x, detail::indeterminate_t) BOOST_NOEXCEPT
  118. {
  119. return x.value == tribool::indeterminate_value;
  120. }
  121. /** @defgroup logical Logical operations
  122. */
  123. //@{
  124. /**
  125. * \brief Computes the logical negation of a tribool
  126. *
  127. * \returns the logical negation of the tribool, according to the
  128. * table:
  129. * <table border=1>
  130. * <tr>
  131. * <th><center><code>!</code></center></th>
  132. * <th/>
  133. * </tr>
  134. * <tr>
  135. * <th><center>false</center></th>
  136. * <td><center>true</center></td>
  137. * </tr>
  138. * <tr>
  139. * <th><center>true</center></th>
  140. * <td><center>false</center></td>
  141. * </tr>
  142. * <tr>
  143. * <th><center>indeterminate</center></th>
  144. * <td><center>indeterminate</center></td>
  145. * </tr>
  146. * </table>
  147. * \throws nothrow
  148. */
  149. BOOST_CONSTEXPR inline tribool operator!(tribool x) BOOST_NOEXCEPT
  150. {
  151. return x.value == tribool::false_value? tribool(true)
  152. :x.value == tribool::true_value? tribool(false)
  153. :tribool(indeterminate);
  154. }
  155. /**
  156. * \brief Computes the logical conjunction of two tribools
  157. *
  158. * \returns the result of logically ANDing the two tribool values,
  159. * according to the following table:
  160. * <table border=1>
  161. * <tr>
  162. * <th><center><code>&amp;&amp;</code></center></th>
  163. * <th><center>false</center></th>
  164. * <th><center>true</center></th>
  165. * <th><center>indeterminate</center></th>
  166. * </tr>
  167. * <tr>
  168. * <th><center>false</center></th>
  169. * <td><center>false</center></td>
  170. * <td><center>false</center></td>
  171. * <td><center>false</center></td>
  172. * </tr>
  173. * <tr>
  174. * <th><center>true</center></th>
  175. * <td><center>false</center></td>
  176. * <td><center>true</center></td>
  177. * <td><center>indeterminate</center></td>
  178. * </tr>
  179. * <tr>
  180. * <th><center>indeterminate</center></th>
  181. * <td><center>false</center></td>
  182. * <td><center>indeterminate</center></td>
  183. * <td><center>indeterminate</center></td>
  184. * </tr>
  185. * </table>
  186. * \throws nothrow
  187. */
  188. BOOST_CONSTEXPR inline tribool operator&&(tribool x, tribool y) BOOST_NOEXCEPT
  189. {
  190. return (static_cast<bool>(!x) || static_cast<bool>(!y))
  191. ? tribool(false)
  192. : ((static_cast<bool>(x) && static_cast<bool>(y)) ? tribool(true) : indeterminate)
  193. ;
  194. }
  195. /**
  196. * \overload
  197. */
  198. BOOST_CONSTEXPR inline tribool operator&&(tribool x, bool y) BOOST_NOEXCEPT
  199. { return y? x : tribool(false); }
  200. /**
  201. * \overload
  202. */
  203. BOOST_CONSTEXPR inline tribool operator&&(bool x, tribool y) BOOST_NOEXCEPT
  204. { return x? y : tribool(false); }
  205. /**
  206. * \overload
  207. */
  208. BOOST_CONSTEXPR inline tribool operator&&(indeterminate_keyword_t, tribool x) BOOST_NOEXCEPT
  209. { return !x? tribool(false) : tribool(indeterminate); }
  210. /**
  211. * \overload
  212. */
  213. BOOST_CONSTEXPR inline tribool operator&&(tribool x, indeterminate_keyword_t) BOOST_NOEXCEPT
  214. { return !x? tribool(false) : tribool(indeterminate); }
  215. /**
  216. * \brief Computes the logical disjunction of two tribools
  217. *
  218. * \returns the result of logically ORing the two tribool values,
  219. * according to the following table:
  220. * <table border=1>
  221. * <tr>
  222. * <th><center><code>||</code></center></th>
  223. * <th><center>false</center></th>
  224. * <th><center>true</center></th>
  225. * <th><center>indeterminate</center></th>
  226. * </tr>
  227. * <tr>
  228. * <th><center>false</center></th>
  229. * <td><center>false</center></td>
  230. * <td><center>true</center></td>
  231. * <td><center>indeterminate</center></td>
  232. * </tr>
  233. * <tr>
  234. * <th><center>true</center></th>
  235. * <td><center>true</center></td>
  236. * <td><center>true</center></td>
  237. * <td><center>true</center></td>
  238. * </tr>
  239. * <tr>
  240. * <th><center>indeterminate</center></th>
  241. * <td><center>indeterminate</center></td>
  242. * <td><center>true</center></td>
  243. * <td><center>indeterminate</center></td>
  244. * </tr>
  245. * </table>
  246. * \throws nothrow
  247. */
  248. BOOST_CONSTEXPR inline tribool operator||(tribool x, tribool y) BOOST_NOEXCEPT
  249. {
  250. return (static_cast<bool>(!x) && static_cast<bool>(!y))
  251. ? tribool(false)
  252. : ((static_cast<bool>(x) || static_cast<bool>(y)) ? tribool(true) : tribool(indeterminate))
  253. ;
  254. }
  255. /**
  256. * \overload
  257. */
  258. BOOST_CONSTEXPR inline tribool operator||(tribool x, bool y) BOOST_NOEXCEPT
  259. { return y? tribool(true) : x; }
  260. /**
  261. * \overload
  262. */
  263. BOOST_CONSTEXPR inline tribool operator||(bool x, tribool y) BOOST_NOEXCEPT
  264. { return x? tribool(true) : y; }
  265. /**
  266. * \overload
  267. */
  268. BOOST_CONSTEXPR inline tribool operator||(indeterminate_keyword_t, tribool x) BOOST_NOEXCEPT
  269. { return x? tribool(true) : tribool(indeterminate); }
  270. /**
  271. * \overload
  272. */
  273. BOOST_CONSTEXPR inline tribool operator||(tribool x, indeterminate_keyword_t) BOOST_NOEXCEPT
  274. { return x? tribool(true) : tribool(indeterminate); }
  275. //@}
  276. /**
  277. * \brief Compare tribools for equality
  278. *
  279. * \returns the result of comparing two tribool values, according to
  280. * the following table:
  281. * <table border=1>
  282. * <tr>
  283. * <th><center><code>==</code></center></th>
  284. * <th><center>false</center></th>
  285. * <th><center>true</center></th>
  286. * <th><center>indeterminate</center></th>
  287. * </tr>
  288. * <tr>
  289. * <th><center>false</center></th>
  290. * <td><center>true</center></td>
  291. * <td><center>false</center></td>
  292. * <td><center>indeterminate</center></td>
  293. * </tr>
  294. * <tr>
  295. * <th><center>true</center></th>
  296. * <td><center>false</center></td>
  297. * <td><center>true</center></td>
  298. * <td><center>indeterminate</center></td>
  299. * </tr>
  300. * <tr>
  301. * <th><center>indeterminate</center></th>
  302. * <td><center>indeterminate</center></td>
  303. * <td><center>indeterminate</center></td>
  304. * <td><center>indeterminate</center></td>
  305. * </tr>
  306. * </table>
  307. * \throws nothrow
  308. */
  309. BOOST_CONSTEXPR inline tribool operator==(tribool x, tribool y) BOOST_NOEXCEPT
  310. {
  311. return (indeterminate(x) || indeterminate(y))
  312. ? indeterminate
  313. : ((x && y) || (!x && !y))
  314. ;
  315. }
  316. /**
  317. * \overload
  318. */
  319. BOOST_CONSTEXPR inline tribool operator==(tribool x, bool y) BOOST_NOEXCEPT { return x == tribool(y); }
  320. /**
  321. * \overload
  322. */
  323. BOOST_CONSTEXPR inline tribool operator==(bool x, tribool y) BOOST_NOEXCEPT { return tribool(x) == y; }
  324. /**
  325. * \overload
  326. */
  327. BOOST_CONSTEXPR inline tribool operator==(indeterminate_keyword_t, tribool x) BOOST_NOEXCEPT
  328. { return tribool(indeterminate) == x; }
  329. /**
  330. * \overload
  331. */
  332. BOOST_CONSTEXPR inline tribool operator==(tribool x, indeterminate_keyword_t) BOOST_NOEXCEPT
  333. { return tribool(indeterminate) == x; }
  334. /**
  335. * \brief Compare tribools for inequality
  336. *
  337. * \returns the result of comparing two tribool values for inequality,
  338. * according to the following table:
  339. * <table border=1>
  340. * <tr>
  341. * <th><center><code>!=</code></center></th>
  342. * <th><center>false</center></th>
  343. * <th><center>true</center></th>
  344. * <th><center>indeterminate</center></th>
  345. * </tr>
  346. * <tr>
  347. * <th><center>false</center></th>
  348. * <td><center>false</center></td>
  349. * <td><center>true</center></td>
  350. * <td><center>indeterminate</center></td>
  351. * </tr>
  352. * <tr>
  353. * <th><center>true</center></th>
  354. * <td><center>true</center></td>
  355. * <td><center>false</center></td>
  356. * <td><center>indeterminate</center></td>
  357. * </tr>
  358. * <tr>
  359. * <th><center>indeterminate</center></th>
  360. * <td><center>indeterminate</center></td>
  361. * <td><center>indeterminate</center></td>
  362. * <td><center>indeterminate</center></td>
  363. * </tr>
  364. * </table>
  365. * \throws nothrow
  366. */
  367. BOOST_CONSTEXPR inline tribool operator!=(tribool x, tribool y) BOOST_NOEXCEPT
  368. {
  369. return (indeterminate(x) || indeterminate(y))
  370. ? indeterminate
  371. : !((x && y) || (!x && !y))
  372. ;
  373. }
  374. /**
  375. * \overload
  376. */
  377. BOOST_CONSTEXPR inline tribool operator!=(tribool x, bool y) BOOST_NOEXCEPT { return x != tribool(y); }
  378. /**
  379. * \overload
  380. */
  381. BOOST_CONSTEXPR inline tribool operator!=(bool x, tribool y) BOOST_NOEXCEPT { return tribool(x) != y; }
  382. /**
  383. * \overload
  384. */
  385. BOOST_CONSTEXPR inline tribool operator!=(indeterminate_keyword_t, tribool x) BOOST_NOEXCEPT
  386. { return tribool(indeterminate) != x; }
  387. /**
  388. * \overload
  389. */
  390. BOOST_CONSTEXPR inline tribool operator!=(tribool x, indeterminate_keyword_t) BOOST_NOEXCEPT
  391. { return x != tribool(indeterminate); }
  392. } } // end namespace boost::logic
  393. // Pull tribool and indeterminate into namespace "boost"
  394. namespace boost {
  395. using logic::tribool;
  396. using logic::indeterminate;
  397. }
  398. /**
  399. * \brief Declare a new name for the third state of a tribool
  400. *
  401. * Use this macro to declare a new name for the third state of a
  402. * tribool. This state can have any number of new names (in addition
  403. * to \c indeterminate), all of which will be equivalent. The new name will be
  404. * placed in the namespace in which the macro is expanded.
  405. *
  406. * Example:
  407. * BOOST_TRIBOOL_THIRD_STATE(true_or_false)
  408. *
  409. * tribool x(true_or_false);
  410. * // potentially set x
  411. * if (true_or_false(x)) {
  412. * // don't know what x is
  413. * }
  414. */
  415. #define BOOST_TRIBOOL_THIRD_STATE(Name) \
  416. inline bool \
  417. Name(boost::logic::tribool x, \
  418. boost::logic::detail::indeterminate_t = \
  419. boost::logic::detail::indeterminate_t()) \
  420. { return x.value == boost::logic::tribool::indeterminate_value; }
  421. #endif // BOOST_LOGIC_TRIBOOL_HPP