Subversion
tristate.hpp
Go to the documentation of this file.
1 /**
2  * @file svnxx/tristate.hpp
3  * @copyright
4  * ====================================================================
5  * Licensed to the Apache Software Foundation (ASF) under one
6  * or more contributor license agreements. See the NOTICE file
7  * distributed with this work for additional information
8  * regarding copyright ownership. The ASF licenses this file
9  * to you under the Apache License, Version 2.0 (the
10  * "License"); you may not use this file except in compliance
11  * with the License. You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing,
16  * software distributed under the License is distributed on an
17  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  * KIND, either express or implied. See the License for the
19  * specific language governing permissions and limitations
20  * under the License.
21  * ====================================================================
22  * @endcopyright
23  */
24 
25 #ifndef SVNXX_TRISTATE_HPP
26 #define SVNXX_TRISTATE_HPP
27 
28 #include "svn_types_impl.h"
29 
30 #include <cstdint>
31 
32 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
33 #include <boost/logic/tribool.hpp>
34 #endif
35 
36 namespace apache {
37 namespace subversion {
38 namespace svnxx {
39 
40 /**
41  * @brief A three-state Boolean-like type.
42  *
43  * @c tristate values represent one of three states:
44  * @li the @e true state (equivalent to Boolean @c true);
45  * @li the @e false state (equivalent to Boolean @c false);
46  * @li the @e unknown state.
47  *
48  * @c tristate constructors, methods and operators are all
49  * compile-time constant expressions and can be used to initialize
50  * other @c constexpr values. And unlike most other types,
51  * comparisons and logical operations between @c tristate values
52  * return a @c tristate, not a @c bool.
53  *
54  * Given a @c tristate value @a t, the state it represents can be
55  * uniquely determined by the following coding pattern:
56  * @code{.cpp}
57  * if (t) {
58  * // t is true
59  * }
60  * else if (!t) {
61  * // t is false
62  * else {
63  * // t is unknown
64  * }
65  * @endcode
66  *
67  * @note Inspired by <tt>boost::tribool</tt>
68  */
69 class tristate
70 {
71  struct impl
72  {
73  void trueval() {};
74  };
75  using safe_bool = void (impl::*)();
76 
77  // The default constructor creates the unkonwn state.
78  constexpr tristate() noexcept
79  : value(unknown_value)
80  {}
81 
82 public:
83  /**
84  * @brief Factory method for the @e unknown state.
85  */
86  static constexpr tristate unknown() noexcept
87  {
88  return tristate(/*unknown_value*/);
89  }
90 
91  /**
92  * @brief Constructor for the @e true and @e false states.
93  */
94  constexpr tristate(bool initial_value) noexcept
95  : value(initial_value ? true_value : false_value)
96  {}
97 
98  /**
99  * @brief Safe conversion to @c bool.
100  * @returns a @e true-like value only when this @c tristate is the
101  * @e true state.
102  */
103  constexpr operator safe_bool() const noexcept
104  {
105  return value == true_value ? &impl::trueval : 0;
106  }
107 
108  /**
109  * @brief Logical negation.
110  * @returns the logical negation of a @c tristate, according to
111  * the following table:
112  * <table border=1>
113  * <tr>
114  * <th><center><code>!</code></center></th>
115  * <th></th>
116  * </tr>
117  * <tr>
118  * <th><center><em>false</em></center></th>
119  * <td><center><em>true</em></center></td>
120  * </tr>
121  * <tr>
122  * <th><center><em>true</em></center></th>
123  * <td><center><em>false</em></center></td>
124  * </tr>
125  * <tr>
126  * <th><center><em>unknown</em></center></th>
127  * <td><center><em>unknown</em></center></td>
128  * </tr>
129  * </table>
130  */
131  constexpr tristate operator!() const noexcept
132  {
133  return (value == false_value ? tristate(true)
134  : (value == true_value ? tristate(false)
135  : tristate::unknown()));
136  }
137 
138 private:
139  // NOTE: Keep these values identical to those in svn_tristate_t!
140  enum : std::uint8_t {
141  false_value = svn_tristate_false,
142  true_value = svn_tristate_true,
143  unknown_value = svn_tristate_unknown
144  } value;
145 
146 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
147 public:
148  /**
149  * @brief Conversion from <tt>boost::tribool</tt>.
150  * @returns a @c tribool value equivalent to the @a t.
151  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
152  */
153  constexpr tristate(boost::tribool t) noexcept
154  : value(boost::indeterminate(t) ? unknown_value
155  : (t ? true_value : false_value))
156  {}
157 
158  /**
159  * @brief Conversion to <tt>boost::tribool</tt>.
160  * @returns a <tt>boost::tribool</tt> value equivalent to the @c
161  * tristate value.
162  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
163  */
164  constexpr operator boost::tribool() const noexcept
165  {
166  return (value == true_value ? boost::tribool(true)
167  : (value == false_value ? boost::tribool(false)
168  : boost::tribool(boost::indeterminate)));
169  }
170 #endif
171 };
172 
173 /**
174  * @related tristate
175  * @brief Test for the @e unknown @c tristate state.
176  * @returns @c true only if @a t is the @e unknown state.
177  */
178 constexpr inline bool unknown(tristate t) noexcept
179 {
180  return bool(t) == bool(!t);
181 }
182 
183 /**
184  * @related tristate
185  * @brief Logical conjunction.
186  * @returns the result of a logical @c AND of two @c tristate
187  * values, according to the following table:
188  * <table border=1>
189  * <tr>
190  * <th><center><code>&amp;&amp;</code></center></th>
191  * <th><center><em>false</em></center></th>
192  * <th><center><em>true</em></center></th>
193  * <th><center><em>unknown</em></center></th>
194  * </tr>
195  * <tr>
196  * <th><center><em>false</em></center></th>
197  * <td><center><em>false</em></center></td>
198  * <td><center><em>false</em></center></td>
199  * <td><center><em>false</em></center></td>
200  * </tr>
201  * <tr>
202  * <th><center><em>true</em></center></th>
203  * <td><center><em>false</em></center></td>
204  * <td><center><em>true</em></center></td>
205  * <td><center><em>unknown</em></center></td>
206  * </tr>
207  * <tr>
208  * <th><center><em>unknown</em></center></th>
209  * <td><center><em>false</em></center></td>
210  * <td><center><em>unknown</em></center></td>
211  * <td><center><em>unknown</em></center></td>
212  * </tr>
213  * </table>
214  */
215 constexpr inline tristate operator&&(tristate t, tristate u) noexcept
216 {
217  return (bool(!t) || bool(!u) ? tristate(false)
218  : (bool(t) && bool(u) ? tristate(true)
219  : tristate::unknown()));
220 }
221 
222 /**
223  * @related tristate
224  * @overload
225  */
226 constexpr inline tristate operator&&(tristate t, bool b) noexcept
227 {
228  return b ? t : tristate(false);
229 }
230 
231 /**
232  * @related tristate
233  * @overload
234  */
235 constexpr inline tristate operator&&(bool b, tristate t) noexcept
236 {
237  return b ? t : tristate(false);
238 }
239 
240 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
241 /**
242  * @related tristate
243  * @overload
244  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
245  */
246 constexpr inline tristate operator&&(tristate t, boost::tribool b) noexcept
247 {
248  return t && tristate(b);
249 }
250 
251 /**
252  * @related tristate
253  * @overload
254  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
255  */
256 constexpr inline tristate operator&&(boost::tribool b, tristate t) noexcept
257 {
258  return tristate(b) && t;
259 }
260 #endif
261 
262 /**
263  * @related tristate
264  * @brief Logical disjunction.
265  * @returns the result of a logical @c OR of two @c tristate
266  * values, according to the following table:
267  * <table border=1>
268  * <tr>
269  * <th><center><code>||</code></center></th>
270  * <th><center><em>false</em></center></th>
271  * <th><center><em>true</em></center></th>
272  * <th><center><em>unknown</em></center></th>
273  * </tr>
274  * <tr>
275  * <th><center><em>false</em></center></th>
276  * <td><center><em>false</em></center></td>
277  * <td><center><em>true</em></center></td>
278  * <td><center><em>unknown</em></center></td>
279  * </tr>
280  * <tr>
281  * <th><center><em>true</em></center></th>
282  * <td><center><em>true</em></center></td>
283  * <td><center><em>true</em></center></td>
284  * <td><center><em>true</em></center></td>
285  * </tr>
286  * <tr>
287  * <th><center><em>unknown</em></center></th>
288  * <td><center><em>unknown</em></center></td>
289  * <td><center><em>true</em></center></td>
290  * <td><center><em>unknown</em></center></td>
291  * </tr>
292  * </table>
293  */
294 constexpr inline tristate operator||(tristate t, tristate u) noexcept
295 {
296  return (bool(!t) && bool(!u) ? tristate(false)
297  : (bool(t) || bool(u) ? tristate(true)
298  : tristate::unknown()));
299 }
300 
301 /**
302  * @related tristate
303  * @overload
304  */
305 constexpr inline tristate operator||(tristate t, bool b) noexcept
306 {
307  return b ? tristate(true) : t;
308 }
309 
310 /**
311  * @related tristate
312  * @overload
313  */
314 constexpr inline tristate operator||(bool b, tristate t) noexcept
315 {
316  return b ? tristate(true) : t;
317 }
318 
319 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
320 /**
321  * @related tristate
322  * @overload
323  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
324  */
325 constexpr inline tristate operator||(tristate t, boost::tribool b) noexcept
326 {
327  return t || tristate(b);
328 }
329 
330 /**
331  * @related tristate
332  * @overload
333  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
334  */
335 constexpr inline tristate operator||(boost::tribool b, tristate t) noexcept
336 {
337  return tristate(b) || t;
338 }
339 #endif
340 
341 /**
342  * @related tristate
343  * @brief Equality comparison.
344  * @returns the result of comparing two @c tristate values for
345  * equality, according to the following table:
346  * <table border=1>
347  * <tr>
348  * <th><center><code>==</code></center></th>
349  * <th><center><em>false</em></center></th>
350  * <th><center><em>true</em></center></th>
351  * <th><center><em>unknown</em></center></th>
352  * </tr>
353  * <tr>
354  * <th><center><em>false</em></center></th>
355  * <td><center><em>true</em></center></td>
356  * <td><center><em>false</em></center></td>
357  * <td><center><em>unknown</em></center></td>
358  * </tr>
359  * <tr>
360  * <th><center><em>true</em></center></th>
361  * <td><center><em>false</em></center></td>
362  * <td><center><em>true</em></center></td>
363  * <td><center><em>unknown</em></center></td>
364  * </tr>
365  * <tr>
366  * <th><center><em>unknown</em></center></th>
367  * <td><center><em>unknown</em></center></td>
368  * <td><center><em>unknown</em></center></td>
369  * <td><center><em>unknown</em></center></td>
370  * </tr>
371  * </table>
372  */
373 constexpr inline tristate operator==(tristate t, tristate u) noexcept
374 {
375  return (unknown(t) || unknown(u) ? tristate::unknown()
376  : ((t && u) || (!t && !u)));
377 }
378 
379 /**
380  * @related tristate
381  * @overload
382  */
383 constexpr inline tristate operator==(tristate t, bool b) noexcept
384 {
385  return t == tristate(b);
386 }
387 
388 /**
389  * @related tristate
390  * @overload
391  */
392 constexpr inline tristate operator==(bool b, tristate t) noexcept
393 {
394  return tristate(b) == t;
395 }
396 
397 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
398 /**
399  * @related tristate
400  * @overload
401  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
402  */
403 constexpr inline tristate operator==(tristate t, boost::tribool b) noexcept
404 {
405  return t == tristate(b);
406 }
407 
408 /**
409  * @related tristate
410  * @overload
411  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
412  */
413 constexpr inline tristate operator==(boost::tribool b, tristate t) noexcept
414 {
415  return tristate(b) == t;
416 }
417 #endif
418 
419 /**
420  * @related tristate
421  * @brief Inquality comparison.
422  * @returns the result of comparing two @c tristate values for
423  * inequality, according to the following table:
424  * <table border=1>
425  * <tr>
426  * <th><center><code>!=</code></center></th>
427  * <th><center><em>false</em></center></th>
428  * <th><center><em>true</em></center></th>
429  * <th><center><em>unknown</em></center></th>
430  * </tr>
431  * <tr>
432  * <th><center><em>false</em></center></th>
433  * <td><center><em>false</em></center></td>
434  * <td><center><em>true</em></center></td>
435  * <td><center><em>unknown</em></center></td>
436  * </tr>
437  * <tr>
438  * <th><center><em>true</em></center></th>
439  * <td><center><em>true</em></center></td>
440  * <td><center><em>false</em></center></td>
441  * <td><center><em>unknown</em></center></td>
442  * </tr>
443  * <tr>
444  * <th><center><em>unknown</em></center></th>
445  * <td><center><em>unknown</em></center></td>
446  * <td><center><em>unknown</em></center></td>
447  * <td><center><em>unknown</em></center></td>
448  * </tr>
449  * </table>
450  */
451 constexpr inline tristate operator!=(tristate t, tristate u) noexcept
452 {
453  return (unknown(t) || unknown(u) ? tristate::unknown()
454  : !((t && u) || (!t && !u)));
455 }
456 
457 /**
458  * @related tristate
459  * @overload
460  */
461 constexpr inline tristate operator!=(tristate t, bool b) noexcept
462 {
463  return t != tristate(b);
464 }
465 
466 /**
467  * @related tristate
468  * @overload
469  */
470 constexpr inline tristate operator!=(bool b, tristate t) noexcept
471 {
472  return tristate(b) != t;
473 }
474 
475 #if defined(SVNXX_USE_BOOST) || defined(DOXYGEN)
476 /**
477  * @related tristate
478  * @overload
479  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
480  */
481 constexpr inline tristate operator!=(tristate t, boost::tribool b) noexcept
482 {
483  return t != tristate(b);
484 }
485 
486 /**
487  * @related tristate
488  * @overload
489  * @note Avalible only if @c SVNXX_USE_BOOST is defined.
490  */
491 constexpr inline tristate operator!=(boost::tribool b, tristate t) noexcept
492 {
493  return tristate(b) != t;
494 }
495 #endif
496 
497 } // namespace svnxx
498 } // namespace subversion
499 } // namespace apache
500 
501 #endif // SVNXX_TRISTATE_HPP
apache::subversion::svnxx::tristate::operator&&
constexpr tristate operator&&(boost::tribool b, tristate t) noexcept
Definition: tristate.hpp:256
svn_types_impl.h
Subversion's data types (common implementation)
apache::subversion::svnxx::tristate::operator==
constexpr tristate operator==(tristate t, tristate u) noexcept
Equality comparison.
Definition: tristate.hpp:373
apache::subversion::svnxx::tristate::operator==
constexpr tristate operator==(tristate t, bool b) noexcept
Definition: tristate.hpp:383
apache::subversion::svnxx::tristate::operator&&
constexpr tristate operator&&(tristate t, boost::tribool b) noexcept
Definition: tristate.hpp:246
apache::subversion::svnxx::tristate::operator!=
constexpr tristate operator!=(tristate t, bool b) noexcept
Definition: tristate.hpp:461
apache::subversion::svnxx::tristate::tristate
constexpr tristate(boost::tribool t) noexcept
Conversion from boost::tribool.
Definition: tristate.hpp:153
svn_tristate_true
@ svn_tristate_true
state known to be true
Definition: svn_types_impl.h:87
apache::subversion::svnxx::tristate::operator!=
constexpr tristate operator!=(bool b, tristate t) noexcept
Definition: tristate.hpp:470
apache::subversion::svnxx::tristate::operator&&
constexpr tristate operator&&(bool b, tristate t) noexcept
Definition: tristate.hpp:235
apache::subversion::svnxx::tristate::operator!=
constexpr tristate operator!=(boost::tribool b, tristate t) noexcept
Definition: tristate.hpp:491
apache::subversion::svnxx::tristate::operator!=
constexpr tristate operator!=(tristate t, boost::tribool b) noexcept
Definition: tristate.hpp:481
apache::subversion::svnxx::tristate::operator&&
constexpr tristate operator&&(tristate t, bool b) noexcept
Definition: tristate.hpp:226
apache::subversion::svnxx::tristate::operator!
constexpr tristate operator!() const noexcept
Logical negation.
Definition: tristate.hpp:131
apache::subversion::svnxx::tristate::operator&&
constexpr tristate operator&&(tristate t, tristate u) noexcept
Logical conjunction.
Definition: tristate.hpp:215
apache::subversion::svnxx::tristate::operator||
constexpr tristate operator||(tristate t, bool b) noexcept
Definition: tristate.hpp:305
apache::subversion::svnxx::tristate::unknown
static constexpr tristate unknown() noexcept
Factory method for the unknown state.
Definition: tristate.hpp:86
apache::subversion::svnxx::tristate::operator||
constexpr tristate operator||(bool b, tristate t) noexcept
Definition: tristate.hpp:314
apache::subversion::svnxx::tristate::operator||
constexpr tristate operator||(boost::tribool b, tristate t) noexcept
Definition: tristate.hpp:335
apache::subversion::svnxx::tristate::operator==
constexpr tristate operator==(boost::tribool b, tristate t) noexcept
Definition: tristate.hpp:413
svn_tristate_false
@ svn_tristate_false
state known to be false (the constant does not evaulate to false)
Definition: svn_types_impl.h:85
apache::subversion::svnxx::tristate::operator==
constexpr tristate operator==(bool b, tristate t) noexcept
Definition: tristate.hpp:392
apache::subversion::svnxx::tristate::unknown
constexpr bool unknown(tristate t) noexcept
Test for the unknown tristate state.
Definition: tristate.hpp:178
apache::subversion::svnxx::tristate::tristate
constexpr tristate(bool initial_value) noexcept
Constructor for the true and false states.
Definition: tristate.hpp:94
apache::subversion::svnxx::tristate::operator!=
constexpr tristate operator!=(tristate t, tristate u) noexcept
Inquality comparison.
Definition: tristate.hpp:451
apache::subversion::svnxx::tristate
A three-state Boolean-like type.
Definition: tristate.hpp:69
apache::subversion::svnxx::tristate::operator||
constexpr tristate operator||(tristate t, boost::tribool b) noexcept
Definition: tristate.hpp:325
apache::subversion::svnxx::tristate::operator||
constexpr tristate operator||(tristate t, tristate u) noexcept
Logical disjunction.
Definition: tristate.hpp:294
apache::subversion::svnxx::tristate::operator==
constexpr tristate operator==(tristate t, boost::tribool b) noexcept
Definition: tristate.hpp:403
svn_tristate_unknown
@ svn_tristate_unknown
state could be true or false
Definition: svn_types_impl.h:89