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