tribool.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  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. #if BOOST_WORKAROUND(_MSC_VER, >= 1200)
  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(__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. inline bool
  53. indeterminate(tribool x,
  54. detail::indeterminate_t dummy = detail::indeterminate_t());
  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. private:
  64. /// INTERNAL ONLY
  65. struct dummy {
  66. void nonnull() {};
  67. };
  68. typedef void (dummy::*safe_bool)();
  69. public:
  70. /**
  71. * Construct a new 3-state boolean value with the value 'false'.
  72. *
  73. * \throws nothrow
  74. */
  75. tribool() : value(false_value) {}
  76. /**
  77. * Construct a new 3-state boolean value with the given boolean
  78. * value, which may be \c true or \c false.
  79. *
  80. * \throws nothrow
  81. */
  82. tribool(bool value) : value(value? true_value : false_value) {}
  83. /**
  84. * Construct a new 3-state boolean value with an indeterminate value.
  85. *
  86. * \throws nothrow
  87. */
  88. tribool(indeterminate_keyword_t) : value(indeterminate_value) {}
  89. /**
  90. * Use a 3-state boolean in a boolean context. Will evaluate true in a
  91. * boolean context only when the 3-state boolean is definitely true.
  92. *
  93. * \returns true if the 3-state boolean is true, false otherwise
  94. * \throws nothrow
  95. */
  96. operator safe_bool() const
  97. {
  98. return value == true_value? &dummy::nonnull : 0;
  99. }
  100. /**
  101. * The actual stored value in this 3-state boolean, which may be false, true,
  102. * or indeterminate.
  103. */
  104. enum value_t { false_value, true_value, indeterminate_value } value;
  105. };
  106. // Check if the given tribool has an indeterminate value. Also doubles as a
  107. // keyword for the 'indeterminate' value
  108. inline bool indeterminate(tribool x, detail::indeterminate_t)
  109. {
  110. return x.value == tribool::indeterminate_value;
  111. }
  112. /** @defgroup logical Logical operations
  113. */
  114. //@{
  115. /**
  116. * \brief Computes the logical negation of a tribool
  117. *
  118. * \returns the logical negation of the tribool, according to the
  119. * table:
  120. * <table border=1>
  121. * <tr>
  122. * <th><center><code>!</code></center></th>
  123. * <th/>
  124. * </tr>
  125. * <tr>
  126. * <th><center>false</center></th>
  127. * <td><center>true</center></td>
  128. * </tr>
  129. * <tr>
  130. * <th><center>true</center></th>
  131. * <td><center>false</center></td>
  132. * </tr>
  133. * <tr>
  134. * <th><center>indeterminate</center></th>
  135. * <td><center>indeterminate</center></td>
  136. * </tr>
  137. * </table>
  138. * \throws nothrow
  139. */
  140. inline tribool operator!(tribool x)
  141. {
  142. return x.value == tribool::false_value? tribool(true)
  143. :x.value == tribool::true_value? tribool(false)
  144. :tribool(indeterminate);
  145. }
  146. /**
  147. * \brief Computes the logical conjuction of two tribools
  148. *
  149. * \returns the result of logically ANDing the two tribool values,
  150. * according to the following table:
  151. * <table border=1>
  152. * <tr>
  153. * <th><center><code>&amp;&amp;</code></center></th>
  154. * <th><center>false</center></th>
  155. * <th><center>true</center></th>
  156. * <th><center>indeterminate</center></th>
  157. * </tr>
  158. * <tr>
  159. * <th><center>false</center></th>
  160. * <td><center>false</center></td>
  161. * <td><center>false</center></td>
  162. * <td><center>false</center></td>
  163. * </tr>
  164. * <tr>
  165. * <th><center>true</center></th>
  166. * <td><center>false</center></td>
  167. * <td><center>true</center></td>
  168. * <td><center>indeterminate</center></td>
  169. * </tr>
  170. * <tr>
  171. * <th><center>indeterminate</center></th>
  172. * <td><center>false</center></td>
  173. * <td><center>indeterminate</center></td>
  174. * <td><center>indeterminate</center></td>
  175. * </tr>
  176. * </table>
  177. * \throws nothrow
  178. */
  179. inline tribool operator&&(tribool x, tribool y)
  180. {
  181. if (static_cast<bool>(!x) || static_cast<bool>(!y))
  182. return false;
  183. else if (static_cast<bool>(x) && static_cast<bool>(y))
  184. return true;
  185. else
  186. return indeterminate;
  187. }
  188. /**
  189. * \overload
  190. */
  191. inline tribool operator&&(tribool x, bool y)
  192. { return y? x : tribool(false); }
  193. /**
  194. * \overload
  195. */
  196. inline tribool operator&&(bool x, tribool y)
  197. { return x? y : tribool(false); }
  198. /**
  199. * \overload
  200. */
  201. inline tribool operator&&(indeterminate_keyword_t, tribool x)
  202. { return !x? tribool(false) : tribool(indeterminate); }
  203. /**
  204. * \overload
  205. */
  206. inline tribool operator&&(tribool x, indeterminate_keyword_t)
  207. { return !x? tribool(false) : tribool(indeterminate); }
  208. /**
  209. * \brief Computes the logical disjunction of two tribools
  210. *
  211. * \returns the result of logically ORing the two tribool values,
  212. * according to the following table:
  213. * <table border=1>
  214. * <tr>
  215. * <th><center><code>||</code></center></th>
  216. * <th><center>false</center></th>
  217. * <th><center>true</center></th>
  218. * <th><center>indeterminate</center></th>
  219. * </tr>
  220. * <tr>
  221. * <th><center>false</center></th>
  222. * <td><center>false</center></td>
  223. * <td><center>true</center></td>
  224. * <td><center>indeterminate</center></td>
  225. * </tr>
  226. * <tr>
  227. * <th><center>true</center></th>
  228. * <td><center>true</center></td>
  229. * <td><center>true</center></td>
  230. * <td><center>true</center></td>
  231. * </tr>
  232. * <tr>
  233. * <th><center>indeterminate</center></th>
  234. * <td><center>indeterminate</center></td>
  235. * <td><center>true</center></td>
  236. * <td><center>indeterminate</center></td>
  237. * </tr>
  238. * </table>
  239. * \throws nothrow
  240. */
  241. inline tribool operator||(tribool x, tribool y)
  242. {
  243. if (static_cast<bool>(!x) && static_cast<bool>(!y))
  244. return false;
  245. else if (static_cast<bool>(x) || static_cast<bool>(y))
  246. return true;
  247. else
  248. return indeterminate;
  249. }
  250. /**
  251. * \overload
  252. */
  253. inline tribool operator||(tribool x, bool y)
  254. { return y? tribool(true) : x; }
  255. /**
  256. * \overload
  257. */
  258. inline tribool operator||(bool x, tribool y)
  259. { return x? tribool(true) : y; }
  260. /**
  261. * \overload
  262. */
  263. inline tribool operator||(indeterminate_keyword_t, tribool x)
  264. { return x? tribool(true) : tribool(indeterminate); }
  265. /**
  266. * \overload
  267. */
  268. inline tribool operator||(tribool x, indeterminate_keyword_t)
  269. { return x? tribool(true) : tribool(indeterminate); }
  270. //@}
  271. /**
  272. * \brief Compare tribools for equality
  273. *
  274. * \returns the result of comparing two tribool values, according to
  275. * the following table:
  276. * <table border=1>
  277. * <tr>
  278. * <th><center><code>==</code></center></th>
  279. * <th><center>false</center></th>
  280. * <th><center>true</center></th>
  281. * <th><center>indeterminate</center></th>
  282. * </tr>
  283. * <tr>
  284. * <th><center>false</center></th>
  285. * <td><center>true</center></td>
  286. * <td><center>false</center></td>
  287. * <td><center>indeterminate</center></td>
  288. * </tr>
  289. * <tr>
  290. * <th><center>true</center></th>
  291. * <td><center>false</center></td>
  292. * <td><center>true</center></td>
  293. * <td><center>indeterminate</center></td>
  294. * </tr>
  295. * <tr>
  296. * <th><center>indeterminate</center></th>
  297. * <td><center>indeterminate</center></td>
  298. * <td><center>indeterminate</center></td>
  299. * <td><center>indeterminate</center></td>
  300. * </tr>
  301. * </table>
  302. * \throws nothrow
  303. */
  304. inline tribool operator==(tribool x, tribool y)
  305. {
  306. if (indeterminate(x) || indeterminate(y))
  307. return indeterminate;
  308. else
  309. return (x && y) || (!x && !y);
  310. }
  311. /**
  312. * \overload
  313. */
  314. inline tribool operator==(tribool x, bool y) { return x == tribool(y); }
  315. /**
  316. * \overload
  317. */
  318. inline tribool operator==(bool x, tribool y) { return tribool(x) == y; }
  319. /**
  320. * \overload
  321. */
  322. inline tribool operator==(indeterminate_keyword_t, tribool x)
  323. { return tribool(indeterminate) == x; }
  324. /**
  325. * \overload
  326. */
  327. inline tribool operator==(tribool x, indeterminate_keyword_t)
  328. { return tribool(indeterminate) == x; }
  329. /**
  330. * \brief Compare tribools for inequality
  331. *
  332. * \returns the result of comparing two tribool values for inequality,
  333. * according to the following table:
  334. * <table border=1>
  335. * <tr>
  336. * <th><center><code>!=</code></center></th>
  337. * <th><center>false</center></th>
  338. * <th><center>true</center></th>
  339. * <th><center>indeterminate</center></th>
  340. * </tr>
  341. * <tr>
  342. * <th><center>false</center></th>
  343. * <td><center>false</center></td>
  344. * <td><center>true</center></td>
  345. * <td><center>indeterminate</center></td>
  346. * </tr>
  347. * <tr>
  348. * <th><center>true</center></th>
  349. * <td><center>true</center></td>
  350. * <td><center>false</center></td>
  351. * <td><center>indeterminate</center></td>
  352. * </tr>
  353. * <tr>
  354. * <th><center>indeterminate</center></th>
  355. * <td><center>indeterminate</center></td>
  356. * <td><center>indeterminate</center></td>
  357. * <td><center>indeterminate</center></td>
  358. * </tr>
  359. * </table>
  360. * \throws nothrow
  361. */
  362. inline tribool operator!=(tribool x, tribool y)
  363. {
  364. if (indeterminate(x) || indeterminate(y))
  365. return indeterminate;
  366. else
  367. return !((x && y) || (!x && !y));
  368. }
  369. /**
  370. * \overload
  371. */
  372. inline tribool operator!=(tribool x, bool y) { return x != tribool(y); }
  373. /**
  374. * \overload
  375. */
  376. inline tribool operator!=(bool x, tribool y) { return tribool(x) != y; }
  377. /**
  378. * \overload
  379. */
  380. inline tribool operator!=(indeterminate_keyword_t, tribool x)
  381. { return tribool(indeterminate) != x; }
  382. /**
  383. * \overload
  384. */
  385. inline tribool operator!=(tribool x, indeterminate_keyword_t)
  386. { return x != tribool(indeterminate); }
  387. } } // end namespace boost::logic
  388. // Pull tribool and indeterminate into namespace "boost"
  389. namespace boost {
  390. using logic::tribool;
  391. using logic::indeterminate;
  392. }
  393. /**
  394. * \brief Declare a new name for the third state of a tribool
  395. *
  396. * Use this macro to declare a new name for the third state of a
  397. * tribool. This state can have any number of new names (in addition
  398. * to \c indeterminate), all of which will be equivalent. The new name will be
  399. * placed in the namespace in which the macro is expanded.
  400. *
  401. * Example:
  402. * BOOST_TRIBOOL_THIRD_STATE(true_or_false)
  403. *
  404. * tribool x(true_or_false);
  405. * // potentially set x
  406. * if (true_or_false(x)) {
  407. * // don't know what x is
  408. * }
  409. */
  410. #define BOOST_TRIBOOL_THIRD_STATE(Name) \
  411. inline bool \
  412. Name(boost::logic::tribool x, \
  413. boost::logic::detail::indeterminate_t dummy = \
  414. boost::logic::detail::indeterminate_t()) \
  415. { return x.value == boost::logic::tribool::indeterminate_value; }
  416. #endif // BOOST_LOGIC_TRIBOOL_HPP