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
36namespace apache {
37namespace subversion {
38namespace 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 */
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
82public:
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
138private:
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)
147public:
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 */
178constexpr 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 */
215constexpr 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 */
226constexpr inline tristate operator&&(tristate t, bool b) noexcept
227{
228 return b ? t : tristate(false);
229}
230
231/**
232 * @related tristate
233 * @overload
234 */
235constexpr 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 */
246constexpr 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 */
256constexpr 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 */
294constexpr 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 */
305constexpr inline tristate operator||(tristate t, bool b) noexcept
306{
307 return b ? tristate(true) : t;
308}
309
310/**
311 * @related tristate
312 * @overload
313 */
314constexpr 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 */
325constexpr 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 */
335constexpr 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 */
373constexpr 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 */
383constexpr inline tristate operator==(tristate t, bool b) noexcept
384{
385 return t == tristate(b);
386}
387
388/**
389 * @related tristate
390 * @overload
391 */
392constexpr 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 */
403constexpr 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 */
413constexpr 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 */
451constexpr 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 */
461constexpr inline tristate operator!=(tristate t, bool b) noexcept
462{
463 return t != tristate(b);
464}
465
466/**
467 * @related tristate
468 * @overload
469 */
470constexpr 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 */
481constexpr 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 */
491constexpr 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
A three-state Boolean-like type.
Definition: tristate.hpp:70
constexpr bool unknown(tristate t) noexcept
Test for the unknown tristate state.
Definition: tristate.hpp:178
static constexpr tristate unknown() noexcept
Factory method for the unknown state.
Definition: tristate.hpp:86
constexpr tristate operator==(tristate t, bool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:383
constexpr tristate operator!=(tristate t, boost::tribool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:481
constexpr tristate operator||(boost::tribool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:335
constexpr tristate operator&&(boost::tribool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:256
constexpr tristate operator&&(tristate t, bool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:226
constexpr tristate operator==(boost::tribool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:413
constexpr tristate(bool initial_value) noexcept
Constructor for the true and false states.
Definition: tristate.hpp:94
constexpr tristate operator&&(bool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:235
constexpr tristate operator!=(tristate t, bool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:461
constexpr tristate operator!=(tristate t, tristate u) noexcept
Inquality comparison.
Definition: tristate.hpp:451
constexpr tristate operator||(bool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:314
constexpr tristate operator||(tristate t, tristate u) noexcept
Logical disjunction.
Definition: tristate.hpp:294
constexpr tristate operator||(tristate t, bool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:305
constexpr tristate(boost::tribool t) noexcept
Conversion from boost::tribool.
Definition: tristate.hpp:153
constexpr tristate operator&&(tristate t, boost::tribool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:246
constexpr tristate operator==(tristate t, tristate u) noexcept
Equality comparison.
Definition: tristate.hpp:373
constexpr tristate operator&&(tristate t, tristate u) noexcept
Logical conjunction.
Definition: tristate.hpp:215
constexpr tristate operator!=(boost::tribool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:491
constexpr tristate operator!() const noexcept
Logical negation.
Definition: tristate.hpp:131
constexpr tristate operator==(bool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:392
constexpr tristate operator==(tristate t, boost::tribool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:403
constexpr tristate operator!=(bool b, tristate t) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:470
constexpr tristate operator||(tristate t, boost::tribool b) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: tristate.hpp:325
Subversion's data types (common implementation)
@ svn_tristate_unknown
state could be true or false
@ svn_tristate_true
state known to be true
@ svn_tristate_false
state known to be false (the constant does not evaulate to false)