A library for working with phylogenetic and population genetic data.
v0.27.0
optional.hpp
Go to the documentation of this file.
1 #ifndef GENESIS_UTILS_CONTAINERS_OPTIONAL_H_
2 #define GENESIS_UTILS_CONTAINERS_OPTIONAL_H_
3 
4 /*
5  Genesis - A toolkit for working with phylogenetic data.
6  Copyright (C) 2014-2022 Lucas Czech
7 
8  This program is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21  Contact:
22  Lucas Czech <lczech@carnegiescience.edu>
23  Department of Plant Biology, Carnegie Institution For Science
24  260 Panama Street, Stanford, CA 94305, USA
25 */
26 
27 /*
28  The code below is adapted from https://github.com/martinmoene/optional-bare
29  We heavily modified the code to fit our needs, but the basic functionaly is the same.
30 
31  Copyright 2017-2019 by Martin Moene
32  Distributed under the Boost Software License, Version 1.0.
33  See http://www.boost.org/LICENSE_1_0.txt
34 
35  Boost Software License - Version 1.0 - August 17th, 2003
36 
37  Permission is hereby granted, free of charge, to any person or organization
38  obtaining a copy of the software and accompanying documentation covered by
39  this license (the "Software") to use, reproduce, display, distribute,
40  execute, and transmit the Software, and to prepare derivative works of the
41  Software, and to permit third-parties to whom the Software is furnished to
42  do so, all subject to the following:
43 
44  The copyright notices in the Software and this entire statement, including
45  the above license grant, this restriction and the following disclaimer,
46  must be included in all copies of the Software, in whole or in part, and
47  all derivative works of the Software, unless such copies or derivative
48  works are solely in the form of machine-executable object code generated by
49  a source language processor.
50 
51  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
52  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
53  FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
54  SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
55  FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
56  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
57  DEALINGS IN THE SOFTWARE.
58 */
59 
67 // =================================================================================================
68 // Prelude
69 // =================================================================================================
70 
71 // C++ language version detection:
72 // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
73 #ifndef GENESIS_OPTIONAL_CPLUSPLUS
74 # if defined(_MSVC_LANG ) && !defined(__clang__)
75 # define GENESIS_OPTIONAL_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
76 # else
77 # define GENESIS_OPTIONAL_CPLUSPLUS __cplusplus
78 # endif
79 #endif
80 
81 // Check if C++17 std::optional is available:
82 #if ( GENESIS_OPTIONAL_CPLUSPLUS >= 201703L ) && defined( __has_include )
83 # if __has_include( <optional> )
84 # define GENESIS_OPTIONAL_HAVE_STD_OPTIONAL 1
85 # else
86 # define GENESIS_OPTIONAL_HAVE_STD_OPTIONAL 0
87 # endif
88 #else
89 # define GENESIS_OPTIONAL_HAVE_STD_OPTIONAL 0
90 #endif
91 
92 // Use C++17 std::optional if available and requested:
93 // Currently, we default to using std::optional if it is available.
94 // Might make this configurable in the future.
95 #define GENESIS_OPTIONAL_USES_STD_OPTIONAL GENESIS_OPTIONAL_HAVE_STD_OPTIONAL
96 
97 // =================================================================================================
98 // Using std::optional
99 // =================================================================================================
100 
101 #if GENESIS_OPTIONAL_USES_STD_OPTIONAL
102 
103 #include <optional>
104 #include <utility>
105 
106 // Add the C++17 std::optional to our namespace, so that our classes can use tham as if they
107 // were our own. This is a bit ugly, but good enough for now. Users that compile genesis with
108 // C++17 or later will still be able to use std::optional with our classes, as the compiler
109 // sees through the typedefs here.
110 namespace genesis {
111 namespace utils {
112 
113  template<class T>
114  using Optional = std::optional<T>;
115  using BadOptionalAccess = std::bad_optional_access;
116 
117  using std::nullopt;
118  using std::nullopt_t;
119 
120  using std::make_optional;
121 
122 } // namespace utils
123 } // namespace genesis
124 
125 // =================================================================================================
126 // Using optional-bare
127 // =================================================================================================
128 
129 #else // GENESIS_OPTIONAL_USES_STD_OPTIONAL
130 
131 #include <cassert>
132 #include <stdexcept>
133 
134 namespace genesis {
135 namespace utils {
136 
140 struct nullopt_t
141 {
142  struct init{};
144 };
145 
149 const nullopt_t nullopt(( nullopt_t::init() ));
150 // (extra parenthesis to prevent the most vexing parse)
151 
155 class BadOptionalAccess : public std::logic_error
156 {
157 public:
158  explicit BadOptionalAccess()
159  : std::logic_error( "Bad Optional access" )
160  {}
161 };
162 
163 // ===========================================================================
164 // Optional
165 // ===========================================================================
166 
177 template< typename T >
178 class Optional
179 {
180 public:
181 
182  // -------------------------------------------------------------------------
183  // Typedefs and Enums
184  // -------------------------------------------------------------------------
185 
186  typedef T value_type;
187 
188  // -------------------------------------------------------------------------
189  // Constructors and Rule of Five
190  // -------------------------------------------------------------------------
191 
193  : has_value_( false )
194  {}
195 
197  : has_value_( false )
198  {}
199 
200  Optional( T const & arg )
201  : has_value_( true )
202  , value_ ( arg )
203  {}
204 
205  Optional( T && arg )
206  : has_value_( true )
207  , value_ ( std::move( arg ))
208  {}
209 
210  template< class U >
211  Optional( Optional<U> const & other )
212  : has_value_( other.has_value() )
213  {
214  if ( other.has_value() ){
215  value_ = other.value();
216  }
217  }
218 
219  template< class U >
220  Optional( Optional<U> && other )
221  : has_value_( other.has_value() )
222  {
223  if ( other.has_value() ){
224  value_ = std::move( other.value() );
225  }
226  }
227 
229  {
230  reset();
231  return *this;
232  }
233 
234  Optional & operator=( T const & other )
235  {
236  has_value_ = true;
237  value_ = other;
238  return *this;
239  }
240 
241  Optional & operator=( T && other )
242  {
243  has_value_ = true;
244  value_ = std::move( other );
245  return *this;
246  }
247 
248  template< class U >
249  Optional & operator=( Optional<U> const & other )
250  {
251  has_value_ = other.has_value();
252  if ( other.has_value() ) {
253  value_ = other.value();
254  }
255  return *this;
256  }
257 
258  template< class U >
260  {
261  has_value_ = other.has_value();
262  if ( other.has_value() ) {
263  value_ = std::move( other.value() );
264  }
265  return *this;
266  }
267 
268  void swap( Optional & rhs )
269  {
270  using std::swap;
271  if ( has_value() && rhs.has_value() ) { swap( **this, *rhs ); }
272  else if( ! has_value() && rhs.has_value() ) { initialize_( *rhs ); rhs.reset(); }
273  else if( has_value() && ! rhs.has_value() ) { rhs.initialize_( **this ); reset(); }
274  // else: both empty, nothing to do
275  }
276 
277  // -------------------------------------------------------------------------
278  // Observers
279  // -------------------------------------------------------------------------
280 
281  value_type const * operator->() const
282  {
283  assert( has_value() );
284  return &value_;
285  }
286 
288  {
289  assert( has_value() );
290  return &value_;
291  }
292 
293  value_type const & operator*() const
294  {
295  assert( has_value() );
296  return value_;
297  }
298 
300  {
301  assert( has_value() );
302  return value_;
303  }
304 
305  explicit operator bool() const
306  {
307  return has_value();
308  }
309 
310  bool has_value() const
311  {
312  return has_value_;
313  }
314 
315  value_type const & value() const
316  {
317  if( ! has_value() ) {
318  throw BadOptionalAccess();
319  }
320  assert( has_value() );
321  return value_;
322  }
323 
325  {
326  if( ! has_value() ) {
327  throw BadOptionalAccess();
328  }
329  assert( has_value() );
330  return value_;
331  }
332 
333  template< class U >
334  value_type value_or( U const & v ) const
335  {
336  return has_value() ? value() : static_cast<value_type>( v );
337  }
338 
339  // -------------------------------------------------------------------------
340  // Modifiers
341  // -------------------------------------------------------------------------
342 
343  void reset()
344  {
345  has_value_ = false;
346  }
347 
348  // -------------------------------------------------------------------------
349  // Internal Members
350  // -------------------------------------------------------------------------
351 
352 private:
353 
354  template< typename V >
355  void initialize_( V const & value )
356  {
357  assert( ! has_value() );
358  value_ = value;
359  has_value_ = true;
360  }
361 
362 private:
363 
364  bool has_value_;
365  value_type value_;
366 
367 };
368 
369 // ===========================================================================
370 // Relational operators
371 // ===========================================================================
372 
373 template< typename T, typename U >
374 inline bool operator==( Optional<T> const & x, Optional<U> const & y )
375 {
376  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
377 }
378 
379 template< typename T, typename U >
380 inline bool operator!=( Optional<T> const & x, Optional<U> const & y )
381 {
382  return !(x == y);
383 }
384 
385 template< typename T, typename U >
386 inline bool operator<( Optional<T> const & x, Optional<U> const & y )
387 {
388  return (!y) ? false : (!x) ? true : *x < *y;
389 }
390 
391 template< typename T, typename U >
392 inline bool operator>( Optional<T> const & x, Optional<U> const & y )
393 {
394  return (y < x);
395 }
396 
397 template< typename T, typename U >
398 inline bool operator<=( Optional<T> const & x, Optional<U> const & y )
399 {
400  return !(y < x);
401 }
402 
403 template< typename T, typename U >
404 inline bool operator>=( Optional<T> const & x, Optional<U> const & y )
405 {
406  return !(x < y);
407 }
408 
409 // ===========================================================================
410 // Comparison with nullopt
411 // ===========================================================================
412 
413 template< typename T >
414 inline bool operator==( Optional<T> const & x, nullopt_t )
415 {
416  return (!x);
417 }
418 
419 template< typename T >
420 inline bool operator==( nullopt_t, Optional<T> const & x )
421 {
422  return (!x);
423 }
424 
425 template< typename T >
426 inline bool operator!=( Optional<T> const & x, nullopt_t )
427 {
428  return bool(x);
429 }
430 
431 template< typename T >
432 inline bool operator!=( nullopt_t, Optional<T> const & x )
433 {
434  return bool(x);
435 }
436 
437 template< typename T >
438 inline bool operator<( Optional<T> const &, nullopt_t )
439 {
440  return false;
441 }
442 
443 template< typename T >
444 inline bool operator<( nullopt_t, Optional<T> const & x )
445 {
446  return bool(x);
447 }
448 
449 template< typename T >
450 inline bool operator<=( Optional<T> const & x, nullopt_t )
451 {
452  return (!x);
453 }
454 
455 template< typename T >
456 inline bool operator<=( nullopt_t, Optional<T> const & )
457 {
458  return true;
459 }
460 
461 template< typename T >
462 inline bool operator>( Optional<T> const & x, nullopt_t )
463 {
464  return bool(x);
465 }
466 
467 template< typename T >
468 inline bool operator>( nullopt_t, Optional<T> const & )
469 {
470  return false;
471 }
472 
473 template< typename T >
474 inline bool operator>=( Optional<T> const &, nullopt_t )
475 {
476  return true;
477 }
478 
479 template< typename T >
480 inline bool operator>=( nullopt_t, Optional<T> const & x )
481 {
482  return (!x);
483 }
484 
485 // ===========================================================================
486 // Comparison with T
487 // ===========================================================================
488 
489 template< typename T, typename U >
490 inline bool operator==( Optional<T> const & x, U const & v )
491 {
492  return bool(x) ? *x == v : false;
493 }
494 
495 template< typename T, typename U >
496 inline bool operator==( U const & v, Optional<T> const & x )
497 {
498  return bool(x) ? v == *x : false;
499 }
500 
501 template< typename T, typename U >
502 inline bool operator!=( Optional<T> const & x, U const & v )
503 {
504  return bool(x) ? *x != v : true;
505 }
506 
507 template< typename T, typename U >
508 inline bool operator!=( U const & v, Optional<T> const & x )
509 {
510  return bool(x) ? v != *x : true;
511 }
512 
513 template< typename T, typename U >
514 inline bool operator<( Optional<T> const & x, U const & v )
515 {
516  return bool(x) ? *x < v : true;
517 }
518 
519 template< typename T, typename U >
520 inline bool operator<( U const & v, Optional<T> const & x )
521 {
522  return bool(x) ? v < *x : false;
523 }
524 
525 template< typename T, typename U >
526 inline bool operator<=( Optional<T> const & x, U const & v )
527 {
528  return bool(x) ? *x <= v : true;
529 }
530 
531 template< typename T, typename U >
532 inline bool operator<=( U const & v, Optional<T> const & x )
533 {
534  return bool(x) ? v <= *x : false;
535 }
536 
537 template< typename T, typename U >
538 inline bool operator>( Optional<T> const & x, U const & v )
539 {
540  return bool(x) ? *x > v : false;
541 }
542 
543 template< typename T, typename U >
544 inline bool operator>( U const & v, Optional<T> const & x )
545 {
546  return bool(x) ? v > *x : true;
547 }
548 
549 template< typename T, typename U >
550 inline bool operator>=( Optional<T> const & x, U const & v )
551 {
552  return bool(x) ? *x >= v : false;
553 }
554 
555 template< typename T, typename U >
556 inline bool operator>=( U const & v, Optional<T> const & x )
557 {
558  return bool(x) ? v >= *x : true;
559 }
560 
561 // ===========================================================================
562 // Specialized algorithms
563 // ===========================================================================
564 
565 template< typename T >
566 void swap( Optional<T> & x, Optional<T> & y )
567 {
568  x.swap( y );
569 }
570 
574 template< typename T >
575 inline Optional<T> make_optional( T const & v )
576 {
577  return Optional<T>( v );
578 }
579 
580 } // namespace utils
581 } // namespace genesis
582 
583 #endif // GENESIS_OPTIONAL_USES_STD_OPTIONAL
584 
585 #endif // include guard
genesis::utils::operator>
bool operator>(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:392
genesis::utils::Optional::Optional
Optional(Optional< U > &&other)
Definition: optional.hpp:220
genesis::utils::Optional::operator->
value_type * operator->()
Definition: optional.hpp:287
genesis::utils::operator>=
bool operator>=(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:404
genesis::utils::nullopt
const nullopt_t nullopt((nullopt_t::init()))
Optional to indicate an empty value.
genesis::utils::operator!=
bool operator!=(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:380
genesis::utils::Optional::operator*
const value_type & operator*() const
Definition: optional.hpp:293
genesis::utils::nullopt_t::nullopt_t
nullopt_t(init)
Definition: optional.hpp:143
genesis::utils::Optional
Simplistic optional: requires T to be default constructible, copyable.
Definition: optional.hpp:178
genesis::utils::nullopt_t
Type for nullopt.
Definition: optional.hpp:140
genesis::utils::Optional::value
const value_type & value() const
Definition: optional.hpp:315
genesis::utils::Optional::operator=
Optional & operator=(Optional< U > &&other)
Definition: optional.hpp:259
genesis::utils::Optional::operator=
Optional & operator=(Optional< U > const &other)
Definition: optional.hpp:249
genesis::utils::nullopt_t::init
Definition: optional.hpp:142
genesis::utils::Optional::value_or
value_type value_or(U const &v) const
Definition: optional.hpp:334
genesis::utils::Optional::Optional
Optional()
Definition: optional.hpp:192
genesis::utils::Optional::operator=
Optional & operator=(T &&other)
Definition: optional.hpp:241
genesis::utils::Optional::value_type
T value_type
Definition: optional.hpp:186
genesis::utils::Optional::Optional
Optional(T const &arg)
Definition: optional.hpp:200
genesis::population::Variant
A single variant at a position in a chromosome, along with BaseCounts for a set of samples.
Definition: variant.hpp:62
genesis::utils::Optional::Optional
Optional(Optional< U > const &other)
Definition: optional.hpp:211
genesis
Container namespace for all symbols of genesis in order to keep them separate when used as a library.
Definition: placement/formats/edge_color.cpp:42
genesis::utils::Optional::operator->
const value_type * operator->() const
Definition: optional.hpp:281
genesis::utils::operator<=
bool operator<=(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:398
genesis::utils::BadOptionalAccess
Optional access error for empty values.
Definition: optional.hpp:155
genesis::utils::Optional::value
value_type & value()
Definition: optional.hpp:324
genesis::utils::operator<
bool operator<(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:386
genesis::utils::Optional::operator=
Optional & operator=(nullopt_t)
Definition: optional.hpp:228
genesis::utils::Optional::operator*
value_type & operator*()
Definition: optional.hpp:299
genesis::utils::make_optional
Optional< T > make_optional(T const &v)
Convenience function to create an Optional.
Definition: optional.hpp:575
genesis::utils::Optional::reset
void reset()
Definition: optional.hpp:343
genesis::utils::Optional::swap
void swap(Optional &rhs)
Definition: optional.hpp:268
genesis::utils::Optional::Optional
Optional(T &&arg)
Definition: optional.hpp:205
genesis::utils::operator==
bool operator==(Optional< T > const &x, Optional< U > const &y)
Definition: optional.hpp:374
genesis::utils::Optional::operator=
Optional & operator=(T const &other)
Definition: optional.hpp:234
genesis::utils::swap
void swap(Optional< T > &x, Optional< T > &y)
Definition: optional.hpp:566
genesis::utils::Optional::Optional
Optional(nullopt_t)
Definition: optional.hpp:196
genesis::utils::Optional::has_value
bool has_value() const
Definition: optional.hpp:310
genesis::utils::BadOptionalAccess::BadOptionalAccess
BadOptionalAccess()
Definition: optional.hpp:158