optional.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. //
  5. // Copyright (C) 2018 Intel Corporation
  6. #ifndef OPENCV_GAPI_UTIL_OPTIONAL_HPP
  7. #define OPENCV_GAPI_UTIL_OPTIONAL_HPP
  8. #include <opencv2/gapi/util/variant.hpp>
  9. // A poor man's `optional` implementation, incompletely modeled against C++17 spec.
  10. namespace cv
  11. {
  12. namespace util
  13. {
  14. class bad_optional_access: public std::exception
  15. {
  16. public:
  17. virtual const char *what() const noexcept override
  18. {
  19. return "Bad optional access";
  20. }
  21. };
  22. // TODO: nullopt_t
  23. // Interface ///////////////////////////////////////////////////////////////
  24. template<typename T> class optional
  25. {
  26. public:
  27. // Constructors
  28. // NB.: there were issues with Clang 3.8 when =default() was used
  29. // instead {}
  30. optional() {}
  31. optional(const optional&) = default;
  32. explicit optional(T&&) noexcept;
  33. explicit optional(const T&) noexcept;
  34. optional(optional&&) noexcept;
  35. // TODO: optional(nullopt_t) noexcept;
  36. // TODO: optional(const optional<U> &)
  37. // TODO: optional(optional<U> &&)
  38. // TODO: optional(Args&&...)
  39. // TODO: optional(initializer_list<U>)
  40. // TODO: optional(U&& value);
  41. // Assignment
  42. optional& operator=(const optional&) = default;
  43. optional& operator=(optional&&);
  44. // Observers
  45. T* operator-> ();
  46. const T* operator-> () const;
  47. T& operator* ();
  48. const T& operator* () const;
  49. // TODO: && versions
  50. operator bool() const noexcept;
  51. bool has_value() const noexcept;
  52. T& value();
  53. const T& value() const;
  54. // TODO: && versions
  55. template<class U>
  56. T value_or(U &&default_value) const;
  57. void swap(optional &other) noexcept;
  58. void reset() noexcept;
  59. // TODO: emplace
  60. // TODO: operator==, !=, <, <=, >, >=
  61. private:
  62. struct nothing {};
  63. util::variant<nothing, T> m_holder;
  64. };
  65. template<class T>
  66. optional<typename std::decay<T>::type> make_optional(T&& value);
  67. // TODO: Args... and initializer_list versions
  68. // Implementation //////////////////////////////////////////////////////////
  69. template<class T> optional<T>::optional(T &&v) noexcept
  70. : m_holder(std::move(v))
  71. {
  72. }
  73. template<class T> optional<T>::optional(const T &v) noexcept
  74. : m_holder(v)
  75. {
  76. }
  77. template<class T> optional<T>::optional(optional&& rhs) noexcept
  78. : m_holder(std::move(rhs.m_holder))
  79. {
  80. rhs.reset();
  81. }
  82. template<class T> optional<T>& optional<T>::operator=(optional&& rhs)
  83. {
  84. m_holder = std::move(rhs.m_holder);
  85. rhs.reset();
  86. return *this;
  87. }
  88. template<class T> T* optional<T>::operator-> ()
  89. {
  90. return & *(*this);
  91. }
  92. template<class T> const T* optional<T>::operator-> () const
  93. {
  94. return & *(*this);
  95. }
  96. template<class T> T& optional<T>::operator* ()
  97. {
  98. return this->value();
  99. }
  100. template<class T> const T& optional<T>::operator* () const
  101. {
  102. return this->value();
  103. }
  104. template<class T> optional<T>::operator bool() const noexcept
  105. {
  106. return this->has_value();
  107. }
  108. template<class T> bool optional<T>::has_value() const noexcept
  109. {
  110. return util::holds_alternative<T>(m_holder);
  111. }
  112. template<class T> T& optional<T>::value()
  113. {
  114. if (!this->has_value())
  115. throw_error(bad_optional_access());
  116. return util::get<T>(m_holder);
  117. }
  118. template<class T> const T& optional<T>::value() const
  119. {
  120. if (!this->has_value())
  121. throw_error(bad_optional_access());
  122. return util::get<T>(m_holder);
  123. }
  124. template<class T>
  125. template<class U> T optional<T>::value_or(U &&default_value) const
  126. {
  127. return (this->has_value() ? this->value() : T(default_value));
  128. }
  129. template<class T> void optional<T>::swap(optional<T> &other) noexcept
  130. {
  131. m_holder.swap(other.m_holder);
  132. }
  133. template<class T> void optional<T>::reset() noexcept
  134. {
  135. if (this->has_value())
  136. m_holder = nothing{};
  137. }
  138. template<class T>
  139. optional<typename std::decay<T>::type> make_optional(T&& value)
  140. {
  141. return optional<typename std::decay<T>::type>(std::forward<T>(value));
  142. }
  143. } // namespace util
  144. } // namespace cv
  145. #endif // OPENCV_GAPI_UTIL_OPTIONAL_HPP