Open3D (C++ API)  0.18.0+601516a
Optional.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - Open3D: www.open3d.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.open3d.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 // Copyright (C) 2011 - 2012 Andrzej Krzemienski.
8 //
9 // Use, modification, and distribution is subject to the Boost Software
10 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 //
13 // The idea and interface is based on Boost.Optional library
14 // authored by Fernando Luis Cacciola Carballal
15 //
16 // From https://github.com/akrzemi1/Optional
17 //
18 // C10
19 // - Move to `c10` namespace.
20 // - Remove macro use in line 478 because the nvcc device compiler cannot handle
21 // it.
22 // - revise constructor logic so that it is consistent with c++ 17 standard
23 // documented here in (8):
24 // https://en.cppreference.com/w/cpp/utility/optional/optional, and could be
25 // able to support initialization of optionals from convertible type U, also
26 // remove two old constructors optional(const T&) and optional(T&&) as it could
27 // be handled by the template<U=T> case with default template argument.
28 // - `constexpr struct in_place_t {} in_place{}` is moved to
29 // `c10/util/in_place.h`, so that it can also be used in `c10/util/variant.h`.
30 // - Remove special cases for pre-c++14 compilers to make code simpler
31 //
32 //
33 // Open3D
34 // - Namespace change: open3d::utility::optional
35 
36 #pragma once
37 
38 #include <cassert>
39 #include <functional>
40 #include <initializer_list>
41 #include <stdexcept>
42 #include <string>
43 #include <type_traits>
44 #include <utility>
45 
46 #define TR2_OPTIONAL_REQUIRES(...) \
47  typename std::enable_if<__VA_ARGS__::value, bool>::type = false
48 
49 namespace open3d {
50 namespace utility {
51 
52 struct in_place_t {
53  explicit in_place_t() = default;
54 };
55 
56 constexpr in_place_t in_place{};
57 
58 // 20.5.4, optional for object types
59 template <class T>
60 class optional;
61 
62 // 20.5.5, optional for lvalue reference types
63 template <class T>
64 class optional<T&>;
65 
66 // workaround: std utility functions aren't constexpr yet
67 template <class T>
68 inline constexpr T&& constexpr_forward(
69  typename std::remove_reference<T>::type& t) noexcept {
70  return static_cast<T&&>(t);
71 }
72 
73 template <class T>
74 inline constexpr T&& constexpr_forward(
75  typename std::remove_reference<T>::type&& t) noexcept {
76  static_assert(!std::is_lvalue_reference<T>::value, "!!");
77  return static_cast<T&&>(t);
78 }
79 
80 template <class T>
81 inline constexpr typename std::remove_reference<T>::type&& constexpr_move(
82  T&& t) noexcept {
83  return static_cast<typename std::remove_reference<T>::type&&>(t);
84 }
85 
86 #if defined NDEBUG
87 #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
88 #else
89 #define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) \
90  ((CHECK) ? (EXPR) : ([] { assert(!#CHECK); }(), (EXPR)))
91 #endif
92 
93 #if defined(__CUDA_ARCH__)
94 #define TR2_OPTIONAL_HOST_CONSTEXPR
95 #else
96 #define TR2_OPTIONAL_HOST_CONSTEXPR constexpr
97 #endif
98 
99 namespace detail_ {
100 
101 // VS doesn't handle constexpr well, so we need to skip these stuff.
102 #if (defined _MSC_VER)
103 template <typename T>
104 T* static_addressof(T& ref) {
105  return std::addressof(ref);
106 }
107 #else
108 // static_addressof: a constexpr version of addressof
109 template <typename T>
111  template <class X>
112  constexpr static bool has_overload(...) {
113  return false;
114  }
115 
116  template <class X, size_t S = sizeof(std::declval<X&>().operator&())>
117  constexpr static bool has_overload(bool) {
118  return true;
119  }
120 
121  constexpr static bool value = has_overload<T>(true);
122 };
123 
124 template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
125 constexpr T* static_addressof(T& ref) {
126  return &ref;
127 }
128 
129 template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
130 T* static_addressof(T& ref) {
131  return std::addressof(ref);
132 }
133 #endif
134 
135 // the call to convert<A>(b) has return type A and converts b to type A iff b
136 // decltype(b) is implicitly convertible to A
137 template <class U>
138 constexpr U convert(U v) {
139  return v;
140 }
141 
142 } // namespace detail_
143 
144 constexpr struct trivial_init_t {
146 
147 // 20.5.7, Disengaged state indicator
148 struct nullopt_t {
149  struct init {};
150  constexpr explicit nullopt_t(init) {}
151 };
153 
154 // 20.5.8, class bad_optional_access
155 class bad_optional_access : public std::logic_error {
156 public:
157  explicit bad_optional_access(const std::string& what_arg)
158  : logic_error{what_arg} {}
159  explicit bad_optional_access(const char* what_arg)
160  : logic_error{what_arg} {}
161 };
162 
163 template <class T>
164 union storage_t {
165  unsigned char dummy_;
167 
168  constexpr storage_t(trivial_init_t) noexcept : dummy_(){};
169 
170  template <class... Args>
171  constexpr storage_t(Args&&... args)
172  : value_(constexpr_forward<Args>(args)...) {}
173 
175 };
176 
177 template <class T>
179  unsigned char dummy_;
181 
182  constexpr constexpr_storage_t(trivial_init_t) noexcept : dummy_(){};
183 
184  template <class... Args>
185  constexpr constexpr_storage_t(Args&&... args)
186  : value_(constexpr_forward<Args>(args)...) {}
187 
188  ~constexpr_storage_t() = default;
189 };
190 
191 template <class T>
193  bool init_;
195 
196  constexpr optional_base() noexcept : init_(false), storage_(trivial_init){};
197 
198  explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
199 
200  explicit constexpr optional_base(T&& v)
201  : init_(true), storage_(constexpr_move(v)) {}
202 
203  template <class... Args>
204  explicit optional_base(in_place_t, Args&&... args)
205  : init_(true), storage_(constexpr_forward<Args>(args)...) {}
206 
207  template <class U,
208  class... Args,
210  std::is_constructible<T, std::initializer_list<U>>)>
212  std::initializer_list<U> il,
213  Args&&... args)
214  : init_(true), storage_(il, std::forward<Args>(args)...) {}
215 
217  if (init_) storage_.value_.T::~T();
218  }
219 };
220 
221 template <class T>
223  bool init_;
225 
226  constexpr constexpr_optional_base() noexcept
227  : init_(false), storage_(trivial_init){};
228 
229  explicit constexpr constexpr_optional_base(const T& v)
230  : init_(true), storage_(v) {}
231 
232  explicit constexpr constexpr_optional_base(T&& v)
233  : init_(true), storage_(constexpr_move(v)) {}
234 
235  template <class... Args>
236  explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
237  : init_(true), storage_(constexpr_forward<Args>(args)...) {}
238 
239  template <class U,
240  class... Args,
242  std::is_constructible<T, std::initializer_list<U>>)>
244  std::initializer_list<U> il,
245  Args&&... args)
246  : init_(true), storage_(il, std::forward<Args>(args)...) {}
247 
249 };
250 
251 template <class T>
252 using OptionalBase = typename std::conditional<
253  std::is_trivially_destructible<T>::value, // if possible
254  constexpr_optional_base<typename std::remove_const<
255  T>::type>, // use base with trivial destructor
257 
258 template <class T>
259 class optional : private OptionalBase<T> {
260  template <class U> // re-declaration for nvcc on Windows.
261  using OptionalBase = typename std::conditional<
262  std::is_trivially_destructible<U>::value, // if possible
263  constexpr_optional_base<typename std::remove_const<
264  U>::type>, // use base with trivial destructor
266 
267  static_assert(!std::is_same<typename std::decay<T>::type, nullopt_t>::value,
268  "bad T");
269  static_assert(
270  !std::is_same<typename std::decay<T>::type, in_place_t>::value,
271  "bad T");
272 
273  constexpr bool initialized() const noexcept {
274  return OptionalBase<T>::init_;
275  }
276  typename std::remove_const<T>::type* dataptr() {
277  return std::addressof(OptionalBase<T>::storage_.value_);
278  }
279  constexpr const T* dataptr() const {
280  return detail_::static_addressof(OptionalBase<T>::storage_.value_);
281  }
282 
283  constexpr const T& contained_val() const& {
284  return OptionalBase<T>::storage_.value_;
285  }
286  constexpr T&& contained_val() && {
287  return std::move(OptionalBase<T>::storage_.value_);
288  }
289  constexpr T& contained_val() & { return OptionalBase<T>::storage_.value_; }
290 
291  void clear() noexcept {
292  if (initialized()) dataptr()->~T();
293  OptionalBase<T>::init_ = false;
294  }
295 
296  template <class... Args>
297  void initialize(Args&&... args) noexcept(
298  noexcept(T(std::forward<Args>(args)...))) {
299  assert(!OptionalBase<T>::init_);
300  ::new (static_cast<void*>(dataptr())) T(std::forward<Args>(args)...);
301  OptionalBase<T>::init_ = true;
302  }
303 
304  template <class U, class... Args>
305  void initialize(std::initializer_list<U> il, Args&&... args) noexcept(
306  noexcept(T(il, std::forward<Args>(args)...))) {
307  assert(!OptionalBase<T>::init_);
308  ::new (static_cast<void*>(dataptr()))
309  T(il, std::forward<Args>(args)...);
310  OptionalBase<T>::init_ = true;
311  }
312 
313 public:
314  typedef T value_type;
315 
316  // 20.5.5.1, constructors
317  constexpr optional() noexcept : OptionalBase<T>(){};
318  constexpr optional(nullopt_t) noexcept : OptionalBase<T>(){};
319 
320  optional(const optional& rhs) : OptionalBase<T>() {
321  if (rhs.initialized()) {
322  ::new (static_cast<void*>(dataptr())) T(*rhs);
323  OptionalBase<T>::init_ = true;
324  }
325  }
326 
327  optional(optional&& rhs) noexcept(
328  std::is_nothrow_move_constructible<T>::value)
329  : OptionalBase<T>() {
330  if (rhs.initialized()) {
331  ::new (static_cast<void*>(dataptr())) T(std::move(*rhs));
332  OptionalBase<T>::init_ = true;
333  }
334  }
335 
336  // see https://github.com/akrzemi1/Optional/issues/16
337  // and https://en.cppreference.com/w/cpp/utility/optional/optional,
338  // in constructor 8, the std::optional spec can allow initialization
339  // of optionals from convertible type U
340  //
341  // 8 - implicit move construct from value
342  template <typename U = T,
343  TR2_OPTIONAL_REQUIRES(std::is_constructible<T, U&&>::value &&
344  !std::is_same<typename std::decay<U>::type,
345  in_place_t>::value &&
346  !std::is_same<typename std::decay<U>::type,
347  optional<T>>::value &&
348  std::is_convertible<U&&, T>)>
349  constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
350 
351  // 8 - explicit move construct from value
352  template <typename U = T,
353  TR2_OPTIONAL_REQUIRES(std::is_constructible<T, U&&>::value &&
354  !std::is_same<typename std::decay<U>::type,
355  in_place_t>::value &&
356  !std::is_same<typename std::decay<U>::type,
357  optional<T>>::value &&
358  !std::is_convertible<U&&, T>)>
359  explicit constexpr optional(U&& u) : OptionalBase<T>(std::forward<U>(u)) {}
360 
361  template <class... Args>
362  explicit constexpr optional(in_place_t, Args&&... args)
363  : OptionalBase<T>(in_place_t{}, constexpr_forward<Args>(args)...) {}
364 
365  template <class U,
366  class... Args,
368  std::is_constructible<T, std::initializer_list<U>>)>
369  constexpr explicit optional(in_place_t,
370  std::initializer_list<U> il,
371  Args&&... args)
372  : OptionalBase<T>(in_place_t{}, il, constexpr_forward<Args>(args)...) {}
373 
374  // 20.5.4.2, Destructor
375  ~optional() = default;
376 
377  // 20.5.4.3, assignment
379  clear();
380  return *this;
381  }
382 
383  optional& operator=(const optional& rhs) {
384  if (initialized() == true && rhs.initialized() == false)
385  clear();
386  else if (initialized() == false && rhs.initialized() == true)
387  initialize(*rhs);
388  else if (initialized() == true && rhs.initialized() == true)
389  contained_val() = *rhs;
390  return *this;
391  }
392 
393  optional& operator=(optional&& rhs) noexcept(
394  std::is_nothrow_move_assignable<T>::value&&
395  std::is_nothrow_move_constructible<T>::value) {
396  if (initialized() == true && rhs.initialized() == false)
397  clear();
398  else if (initialized() == false && rhs.initialized() == true)
399  initialize(std::move(*rhs));
400  else if (initialized() == true && rhs.initialized() == true)
401  contained_val() = std::move(*rhs);
402  return *this;
403  }
404 
405  template <class U = T>
406  auto operator=(U&& v) -> typename std::enable_if<
407  std::is_constructible<T, U>::value &&
410  (std::is_scalar<T>::value ||
412  std::is_assignable<T&, U>::value,
413  optional&>::type {
414  if (initialized()) {
415  contained_val() = std::forward<U>(v);
416  } else {
417  initialize(std::forward<U>(v));
418  }
419  return *this;
420  }
421 
422  template <class... Args>
423  void emplace(Args&&... args) {
424  clear();
425  initialize(std::forward<Args>(args)...);
426  }
427 
428  template <class U, class... Args>
429  void emplace(std::initializer_list<U> il, Args&&... args) {
430  clear();
431  initialize<U, Args...>(il, std::forward<Args>(args)...);
432  }
433 
434  // 20.5.4.4, Swap
435  void swap(optional<T>& rhs) noexcept(
436  std::is_nothrow_move_constructible<T>::value&& noexcept(
437  std::swap(std::declval<T&>(), std::declval<T&>()))) {
438  if (initialized() == true && rhs.initialized() == false) {
439  rhs.initialize(std::move(**this));
440  clear();
441  } else if (initialized() == false && rhs.initialized() == true) {
442  initialize(std::move(*rhs));
443  rhs.clear();
444  } else if (initialized() == true && rhs.initialized() == true) {
445  using std::swap;
446  swap(**this, *rhs);
447  }
448  }
449 
450  // 20.5.4.5, Observers
451 
452  explicit constexpr operator bool() const noexcept { return initialized(); }
453  constexpr bool has_value() const noexcept { return initialized(); }
454 
456  return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
457  }
458 
460  assert(initialized());
461  return dataptr();
462  }
463 
465  return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
466  }
467 
469  assert(initialized());
470  return contained_val();
471  }
472 
474  assert(initialized());
475  return constexpr_move(contained_val());
476  }
477 
478  TR2_OPTIONAL_HOST_CONSTEXPR T const& value() const& {
479  return initialized()
480  ? contained_val()
481  : (throw bad_optional_access("bad optional access"),
482  contained_val());
483  }
484 
486  return initialized()
487  ? contained_val()
488  : (throw bad_optional_access("bad optional access"),
489  contained_val());
490  }
491 
493  if (!initialized()) throw bad_optional_access("bad optional access");
494  return std::move(contained_val());
495  }
496 
497  template <class V>
498  constexpr T value_or(V&& v) const& {
499  return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
500  }
501 
502  template <class V>
503  constexpr T value_or(V&& v) && {
504  return *this ? constexpr_move(
505  const_cast<optional<T>&>(*this).contained_val())
506  : detail_::convert<T>(constexpr_forward<V>(v));
507  }
508 
509  // 20.6.3.6, modifiers
510  void reset() noexcept { clear(); }
511 };
512 
513 // XXX: please refrain from using optional<T&>, since it is being against with
514 // the optional standard in c++ 17, see the debate and the details here:
515 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3406#rationale.refs
516 // if you need it, consider using optional<std::reference_wrapper<T>> or *
517 // pointer
518 //
519 // we leave the implementation here in case we want to reconsider using it in
520 // the future if it becomes a definitely necessary case.
521 template <class T>
522 class optional<T&> {
523  // add this assert to prevent user from using optional reference as
524  // indicated above
525  static_assert(sizeof(T) == 0,
526  "optional references is ill-formed, \
527  consider use optional of a std::reference_wrapper of type T to \
528  hold a reference if you really need to");
529 
530  static_assert(!std::is_same<T, nullopt_t>::value, "bad T");
531  static_assert(!std::is_same<T, in_place_t>::value, "bad T");
532  T* ref;
533 
534 public:
535  // 20.5.5.1, construction/destruction
536  constexpr optional() noexcept : ref(nullptr) {}
537 
538  constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
539 
540  template <typename U = T>
541  constexpr optional(U& u) noexcept : ref(detail_::static_addressof(u)) {}
542 
543  template <typename U = T>
544  optional(U&&) = delete;
545 
546  constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
547 
548  explicit constexpr optional(in_place_t, T& v) noexcept
549  : ref(detail_::static_addressof(v)) {}
550 
551  explicit optional(in_place_t, T&&) = delete;
552 
553  ~optional() = default;
554 
555  // 20.5.5.2, mutation
557  ref = nullptr;
558  return *this;
559  }
560 
561  // optional& operator=(const optional& rhs) noexcept {
562  // ref = rhs.ref;
563  // return *this;
564  // }
565 
566  // optional& operator=(optional&& rhs) noexcept {
567  // ref = rhs.ref;
568  // return *this;
569  // }
570 
571  template <typename U>
572  auto operator=(U&& rhs) noexcept -> typename std::enable_if<
574  optional&>::type {
575  ref = rhs.ref;
576  return *this;
577  }
578 
579  template <typename U>
580  auto operator=(U&& rhs) noexcept -> typename std::enable_if<
582  optional&>::type = delete;
583 
584  void emplace(T& v) noexcept { ref = detail_::static_addressof(v); }
585 
586  void emplace(T&&) = delete;
587 
588  void swap(optional<T&>& rhs) noexcept { std::swap(ref, rhs.ref); }
589 
590  // 20.5.5.3, observers
592  return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
593  }
594 
596  return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
597  }
598 
599  constexpr T& value() const {
600  return ref ? *ref
601  : (throw bad_optional_access("bad optional access"), *ref);
602  }
603 
604  explicit constexpr operator bool() const noexcept { return ref != nullptr; }
605 
606  constexpr bool has_value() const noexcept { return ref != nullptr; }
607 
608  template <class V>
609  constexpr typename std::decay<T>::type value_or(V&& v) const {
610  return *this ? **this
612  constexpr_forward<V>(v));
613  }
614 
615  // x.x.x.x, modifiers
616  void reset() noexcept { ref = nullptr; }
617 };
618 
619 template <class T>
620 class optional<T&&> {
621  static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
622 };
623 
624 // 20.5.8, Relational operators
625 template <class T>
626 constexpr bool operator==(const optional<T>& x, const optional<T>& y) {
627  return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
628 }
629 
630 template <class T>
631 constexpr bool operator!=(const optional<T>& x, const optional<T>& y) {
632  return !(x == y);
633 }
634 
635 template <class T>
636 constexpr bool operator<(const optional<T>& x, const optional<T>& y) {
637  return (!y) ? false : (!x) ? true : *x < *y;
638 }
639 
640 template <class T>
641 constexpr bool operator>(const optional<T>& x, const optional<T>& y) {
642  return (y < x);
643 }
644 
645 template <class T>
646 constexpr bool operator<=(const optional<T>& x, const optional<T>& y) {
647  return !(y < x);
648 }
649 
650 template <class T>
651 constexpr bool operator>=(const optional<T>& x, const optional<T>& y) {
652  return !(x < y);
653 }
654 
655 // 20.5.9, Comparison with nullopt
656 template <class T>
657 constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept {
658  return (!x);
659 }
660 
661 template <class T>
662 constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept {
663  return (!x);
664 }
665 
666 template <class T>
667 constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept {
668  return bool(x);
669 }
670 
671 template <class T>
672 constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept {
673  return bool(x);
674 }
675 
676 template <class T>
677 constexpr bool operator<(const optional<T>&, nullopt_t) noexcept {
678  return false;
679 }
680 
681 template <class T>
682 constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept {
683  return bool(x);
684 }
685 
686 template <class T>
687 constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept {
688  return (!x);
689 }
690 
691 template <class T>
692 constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept {
693  return true;
694 }
695 
696 template <class T>
697 constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept {
698  return bool(x);
699 }
700 
701 template <class T>
702 constexpr bool operator>(nullopt_t, const optional<T>&) noexcept {
703  return false;
704 }
705 
706 template <class T>
707 constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept {
708  return true;
709 }
710 
711 template <class T>
712 constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept {
713  return (!x);
714 }
715 
716 // 20.5.10, Comparison with T
717 template <class T>
718 constexpr bool operator==(const optional<T>& x, const T& v) {
719  return bool(x) ? *x == v : false;
720 }
721 
722 template <class T>
723 constexpr bool operator==(const T& v, const optional<T>& x) {
724  return bool(x) ? v == *x : false;
725 }
726 
727 template <class T>
728 constexpr bool operator!=(const optional<T>& x, const T& v) {
729  return bool(x) ? *x != v : true;
730 }
731 
732 template <class T>
733 constexpr bool operator!=(const T& v, const optional<T>& x) {
734  return bool(x) ? v != *x : true;
735 }
736 
737 template <class T>
738 constexpr bool operator<(const optional<T>& x, const T& v) {
739  return bool(x) ? *x < v : true;
740 }
741 
742 template <class T>
743 constexpr bool operator>(const T& v, const optional<T>& x) {
744  return bool(x) ? v > *x : true;
745 }
746 
747 template <class T>
748 constexpr bool operator>(const optional<T>& x, const T& v) {
749  return bool(x) ? *x > v : false;
750 }
751 
752 template <class T>
753 constexpr bool operator<(const T& v, const optional<T>& x) {
754  return bool(x) ? v < *x : false;
755 }
756 
757 template <class T>
758 constexpr bool operator>=(const optional<T>& x, const T& v) {
759  return bool(x) ? *x >= v : false;
760 }
761 
762 template <class T>
763 constexpr bool operator<=(const T& v, const optional<T>& x) {
764  return bool(x) ? v <= *x : false;
765 }
766 
767 template <class T>
768 constexpr bool operator<=(const optional<T>& x, const T& v) {
769  return bool(x) ? *x <= v : true;
770 }
771 
772 template <class T>
773 constexpr bool operator>=(const T& v, const optional<T>& x) {
774  return bool(x) ? v >= *x : true;
775 }
776 
777 // Comparison of optional<T&> with T
778 template <class T>
779 constexpr bool operator==(const optional<T&>& x, const T& v) {
780  return bool(x) ? *x == v : false;
781 }
782 
783 template <class T>
784 constexpr bool operator==(const T& v, const optional<T&>& x) {
785  return bool(x) ? v == *x : false;
786 }
787 
788 template <class T>
789 constexpr bool operator!=(const optional<T&>& x, const T& v) {
790  return bool(x) ? *x != v : true;
791 }
792 
793 template <class T>
794 constexpr bool operator!=(const T& v, const optional<T&>& x) {
795  return bool(x) ? v != *x : true;
796 }
797 
798 template <class T>
799 constexpr bool operator<(const optional<T&>& x, const T& v) {
800  return bool(x) ? *x < v : true;
801 }
802 
803 template <class T>
804 constexpr bool operator>(const T& v, const optional<T&>& x) {
805  return bool(x) ? v > *x : true;
806 }
807 
808 template <class T>
809 constexpr bool operator>(const optional<T&>& x, const T& v) {
810  return bool(x) ? *x > v : false;
811 }
812 
813 template <class T>
814 constexpr bool operator<(const T& v, const optional<T&>& x) {
815  return bool(x) ? v < *x : false;
816 }
817 
818 template <class T>
819 constexpr bool operator>=(const optional<T&>& x, const T& v) {
820  return bool(x) ? *x >= v : false;
821 }
822 
823 template <class T>
824 constexpr bool operator<=(const T& v, const optional<T&>& x) {
825  return bool(x) ? v <= *x : false;
826 }
827 
828 template <class T>
829 constexpr bool operator<=(const optional<T&>& x, const T& v) {
830  return bool(x) ? *x <= v : true;
831 }
832 
833 template <class T>
834 constexpr bool operator>=(const T& v, const optional<T&>& x) {
835  return bool(x) ? v >= *x : true;
836 }
837 
838 // Comparison of optional<T const&> with T
839 template <class T>
840 constexpr bool operator==(const optional<const T&>& x, const T& v) {
841  return bool(x) ? *x == v : false;
842 }
843 
844 template <class T>
845 constexpr bool operator==(const T& v, const optional<const T&>& x) {
846  return bool(x) ? v == *x : false;
847 }
848 
849 template <class T>
850 constexpr bool operator!=(const optional<const T&>& x, const T& v) {
851  return bool(x) ? *x != v : true;
852 }
853 
854 template <class T>
855 constexpr bool operator!=(const T& v, const optional<const T&>& x) {
856  return bool(x) ? v != *x : true;
857 }
858 
859 template <class T>
860 constexpr bool operator<(const optional<const T&>& x, const T& v) {
861  return bool(x) ? *x < v : true;
862 }
863 
864 template <class T>
865 constexpr bool operator>(const T& v, const optional<const T&>& x) {
866  return bool(x) ? v > *x : true;
867 }
868 
869 template <class T>
870 constexpr bool operator>(const optional<const T&>& x, const T& v) {
871  return bool(x) ? *x > v : false;
872 }
873 
874 template <class T>
875 constexpr bool operator<(const T& v, const optional<const T&>& x) {
876  return bool(x) ? v < *x : false;
877 }
878 
879 template <class T>
880 constexpr bool operator>=(const optional<const T&>& x, const T& v) {
881  return bool(x) ? *x >= v : false;
882 }
883 
884 template <class T>
885 constexpr bool operator<=(const T& v, const optional<const T&>& x) {
886  return bool(x) ? v <= *x : false;
887 }
888 
889 template <class T>
890 constexpr bool operator<=(const optional<const T&>& x, const T& v) {
891  return bool(x) ? *x <= v : true;
892 }
893 
894 template <class T>
895 constexpr bool operator>=(const T& v, const optional<const T&>& x) {
896  return bool(x) ? v >= *x : true;
897 }
898 
899 // 20.5.12, Specialized algorithms
900 template <class T>
901 void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
902  x.swap(y);
903 }
904 
905 template <class T>
907  return optional<typename std::decay<T>::type>(constexpr_forward<T>(v));
908 }
909 
910 template <class X>
911 constexpr optional<X&> make_optional(std::reference_wrapper<X> v) {
912  return optional<X&>(v.get());
913 }
914 
915 } // namespace utility
916 } // namespace open3d
917 
918 namespace std {
919 template <typename T>
920 struct hash<open3d::utility::optional<T>> {
921  typedef typename hash<T>::result_type result_type;
923 
924  constexpr result_type operator()(argument_type const& arg) const {
925  return arg ? std::hash<T>{}(*arg) : result_type{};
926  }
927 };
928 
929 template <typename T>
930 struct hash<open3d::utility::optional<T&>> {
931  typedef typename hash<T>::result_type result_type;
933 
934  constexpr result_type operator()(argument_type const& arg) const {
935  return arg ? std::hash<T>{}(*arg) : result_type{};
936  }
937 };
938 } // namespace std
939 
940 #undef TR2_OPTIONAL_REQUIRES
941 #undef TR2_OPTIONAL_ASSERTED_EXPRESSION
942 #undef TR2_OPTIONAL_HOST_CONSTEXPR
#define TR2_OPTIONAL_REQUIRES(...)
Definition: Optional.h:46
#define TR2_OPTIONAL_HOST_CONSTEXPR
Definition: Optional.h:96
#define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR)
Definition: Optional.h:89
Definition: Optional.h:155
bad_optional_access(const char *what_arg)
Definition: Optional.h:159
bad_optional_access(const std::string &what_arg)
Definition: Optional.h:157
Definition: Optional.h:522
constexpr T & value() const
Definition: Optional.h:599
constexpr optional(U &u) noexcept
Definition: Optional.h:541
constexpr optional() noexcept
Definition: Optional.h:536
auto operator=(U &&rhs) noexcept -> typename std::enable_if< std::is_same< typename std::decay< U >::type, optional< T & >>::value, optional & >::type
Definition: Optional.h:572
TR2_OPTIONAL_HOST_CONSTEXPR T * operator->() const
Definition: Optional.h:591
TR2_OPTIONAL_HOST_CONSTEXPR T & operator*() const
Definition: Optional.h:595
void reset() noexcept
Definition: Optional.h:616
constexpr optional(nullopt_t) noexcept
Definition: Optional.h:538
void emplace(T &v) noexcept
Definition: Optional.h:584
constexpr std::decay< T >::type value_or(V &&v) const
Definition: Optional.h:609
auto operator=(U &&rhs) noexcept -> typename std::enable_if< !std::is_same< typename std::decay< U >::type, optional< T & >>::value, optional & >::type=delete
optional(in_place_t, T &&)=delete
void swap(optional< T & > &rhs) noexcept
Definition: Optional.h:588
constexpr optional(in_place_t, T &v) noexcept
Definition: Optional.h:548
constexpr bool has_value() const noexcept
Definition: Optional.h:606
optional & operator=(nullopt_t) noexcept
Definition: Optional.h:556
constexpr optional(const optional &rhs) noexcept
Definition: Optional.h:546
Definition: Optional.h:259
constexpr bool has_value() const noexcept
Definition: Optional.h:453
optional & operator=(const optional &rhs)
Definition: Optional.h:383
optional(const optional &rhs)
Definition: Optional.h:320
TR2_OPTIONAL_HOST_CONSTEXPR T && operator*() &&
Definition: Optional.h:473
optional & operator=(nullopt_t) noexcept
Definition: Optional.h:378
T value_type
Definition: Optional.h:314
TR2_OPTIONAL_HOST_CONSTEXPR T const & value() const &
Definition: Optional.h:478
TR2_OPTIONAL_HOST_CONSTEXPR T & operator*() &
Definition: Optional.h:468
constexpr T value_or(V &&v) const &
Definition: Optional.h:498
constexpr optional() noexcept
Definition: Optional.h:317
optional & operator=(optional &&rhs) noexcept(std::is_nothrow_move_assignable< T >::value &&std::is_nothrow_move_constructible< T >::value)
Definition: Optional.h:393
TR2_OPTIONAL_HOST_CONSTEXPR T const & operator*() const &
Definition: Optional.h:464
TR2_OPTIONAL_HOST_CONSTEXPR T & value() &
Definition: Optional.h:485
void emplace(std::initializer_list< U > il, Args &&... args)
Definition: Optional.h:429
constexpr optional(U &&u)
Definition: Optional.h:349
constexpr T value_or(V &&v) &&
Definition: Optional.h:503
void emplace(Args &&... args)
Definition: Optional.h:423
auto operator=(U &&v) -> typename std::enable_if< std::is_constructible< T, U >::value &&!std::is_same< typename std::decay< U >::type, optional< T >>::value &&(std::is_scalar< T >::value||std::is_same< typename std::decay< U >::type, T >::value) &&std::is_assignable< T &, U >::value, optional & >::type
Definition: Optional.h:406
void reset() noexcept
Definition: Optional.h:510
TR2_OPTIONAL_HOST_CONSTEXPR T * operator->()
Definition: Optional.h:459
constexpr optional(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: Optional.h:369
optional(optional &&rhs) noexcept(std::is_nothrow_move_constructible< T >::value)
Definition: Optional.h:327
constexpr optional(in_place_t, Args &&... args)
Definition: Optional.h:362
void swap(optional< T > &rhs) noexcept(std::is_nothrow_move_constructible< T >::value &&noexcept(std::swap(std::declval< T & >(), std::declval< T & >())))
Definition: Optional.h:435
TR2_OPTIONAL_HOST_CONSTEXPR T const * operator->() const
Definition: Optional.h:455
TR2_OPTIONAL_HOST_CONSTEXPR T && value() &&
Definition: Optional.h:492
constexpr optional(nullopt_t) noexcept
Definition: Optional.h:318
char type
Definition: FilePCD.cpp:41
constexpr U convert(U v)
Definition: Optional.h:138
constexpr T * static_addressof(T &ref)
Definition: Optional.h:125
constexpr in_place_t in_place
Definition: Optional.h:56
constexpr struct open3d::utility::trivial_init_t trivial_init
constexpr bool operator<(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:636
constexpr bool operator>=(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:651
constexpr std::remove_reference< T >::type && constexpr_move(T &&t) noexcept
Definition: Optional.h:81
constexpr optional< typename std::decay< T >::type > make_optional(T &&v)
Definition: Optional.h:906
constexpr bool operator==(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:626
typename std::conditional< std::is_trivially_destructible< T >::value, constexpr_optional_base< typename std::remove_const< T >::type >, optional_base< typename std::remove_const< T >::type > >::type OptionalBase
Definition: Optional.h:256
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
Definition: Optional.h:901
constexpr bool operator<=(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:646
constexpr bool operator>(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:641
constexpr nullopt_t nullopt
Definition: Optional.h:152
constexpr bool operator!=(const optional< T > &x, const optional< T > &y)
Definition: Optional.h:631
constexpr T && constexpr_forward(typename std::remove_reference< T >::type &t) noexcept
Definition: Optional.h:68
Definition: PinholeCameraIntrinsic.cpp:16
Definition: Device.h:111
void swap(open3d::core::SmallVectorImpl< T > &LHS, open3d::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Definition: SmallVector.h:1370
constexpr constexpr_optional_base() noexcept
Definition: Optional.h:226
constexpr_storage_t< T > storage_
Definition: Optional.h:224
constexpr constexpr_optional_base(in_place_t, Args &&... args)
Definition: Optional.h:236
constexpr constexpr_optional_base(T &&v)
Definition: Optional.h:232
bool init_
Definition: Optional.h:223
constexpr constexpr_optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: Optional.h:243
constexpr constexpr_optional_base(const T &v)
Definition: Optional.h:229
constexpr static bool value
Definition: Optional.h:121
constexpr static bool has_overload(bool)
Definition: Optional.h:117
constexpr static bool has_overload(...)
Definition: Optional.h:112
Definition: Optional.h:52
Definition: Optional.h:149
Definition: Optional.h:148
constexpr nullopt_t(init)
Definition: Optional.h:150
Definition: Optional.h:192
~optional_base()
Definition: Optional.h:216
bool init_
Definition: Optional.h:193
optional_base(in_place_t, std::initializer_list< U > il, Args &&... args)
Definition: Optional.h:211
storage_t< T > storage_
Definition: Optional.h:194
optional_base(in_place_t, Args &&... args)
Definition: Optional.h:204
constexpr optional_base(const T &v)
Definition: Optional.h:198
constexpr optional_base() noexcept
Definition: Optional.h:196
constexpr optional_base(T &&v)
Definition: Optional.h:200
Definition: Optional.h:144
open3d::utility::optional< T > argument_type
Definition: Optional.h:922
constexpr result_type operator()(argument_type const &arg) const
Definition: Optional.h:924
hash< T >::result_type result_type
Definition: Optional.h:921
open3d::utility::optional< T & > argument_type
Definition: Optional.h:932
constexpr result_type operator()(argument_type const &arg) const
Definition: Optional.h:934
hash< T >::result_type result_type
Definition: Optional.h:931
Definition: Optional.h:178
T value_
Definition: Optional.h:180
constexpr constexpr_storage_t(trivial_init_t) noexcept
Definition: Optional.h:182
unsigned char dummy_
Definition: Optional.h:179
constexpr constexpr_storage_t(Args &&... args)
Definition: Optional.h:185
Definition: Optional.h:164
constexpr storage_t(Args &&... args)
Definition: Optional.h:171
unsigned char dummy_
Definition: Optional.h:165
constexpr storage_t(trivial_init_t) noexcept
Definition: Optional.h:168
~storage_t()
Definition: Optional.h:174
T value_
Definition: Optional.h:166