// This file is part of OpenCV project. // It is subject to the license terms in the LICENSE file found in the top-level directory // of this distribution and at http://opencv.org/license.html. // // Copyright (C) 2018 Intel Corporation #ifndef OPENCV_GAPI_UTIL_OPTIONAL_HPP #define OPENCV_GAPI_UTIL_OPTIONAL_HPP #include // A poor man's `optional` implementation, incompletely modeled against C++17 spec. namespace cv { namespace util { class bad_optional_access: public std::exception { public: virtual const char *what() const noexcept override { return "Bad optional access"; } }; // TODO: nullopt_t // Interface /////////////////////////////////////////////////////////////// template class optional { public: // Constructors // NB.: there were issues with Clang 3.8 when =default() was used // instead {} optional() {} optional(const optional&) = default; explicit optional(T&&) noexcept; explicit optional(const T&) noexcept; optional(optional&&) noexcept; // TODO: optional(nullopt_t) noexcept; // TODO: optional(const optional &) // TODO: optional(optional &&) // TODO: optional(Args&&...) // TODO: optional(initializer_list) // TODO: optional(U&& value); // Assignment optional& operator=(const optional&) = default; optional& operator=(optional&&); // Observers T* operator-> (); const T* operator-> () const; T& operator* (); const T& operator* () const; // TODO: && versions operator bool() const noexcept; bool has_value() const noexcept; T& value(); const T& value() const; // TODO: && versions template T value_or(U &&default_value) const; void swap(optional &other) noexcept; void reset() noexcept; // TODO: emplace // TODO: operator==, !=, <, <=, >, >= private: struct nothing {}; util::variant m_holder; }; template optional::type> make_optional(T&& value); // TODO: Args... and initializer_list versions // Implementation ////////////////////////////////////////////////////////// template optional::optional(T &&v) noexcept : m_holder(std::move(v)) { } template optional::optional(const T &v) noexcept : m_holder(v) { } template optional::optional(optional&& rhs) noexcept : m_holder(std::move(rhs.m_holder)) { rhs.reset(); } template optional& optional::operator=(optional&& rhs) { m_holder = std::move(rhs.m_holder); rhs.reset(); return *this; } template T* optional::operator-> () { return & *(*this); } template const T* optional::operator-> () const { return & *(*this); } template T& optional::operator* () { return this->value(); } template const T& optional::operator* () const { return this->value(); } template optional::operator bool() const noexcept { return this->has_value(); } template bool optional::has_value() const noexcept { return util::holds_alternative(m_holder); } template T& optional::value() { if (!this->has_value()) throw_error(bad_optional_access()); return util::get(m_holder); } template const T& optional::value() const { if (!this->has_value()) throw_error(bad_optional_access()); return util::get(m_holder); } template template T optional::value_or(U &&default_value) const { return (this->has_value() ? this->value() : T(default_value)); } template void optional::swap(optional &other) noexcept { m_holder.swap(other.m_holder); } template void optional::reset() noexcept { if (this->has_value()) m_holder = nothing{}; } template optional::type> make_optional(T&& value) { return optional::type>(std::forward(value)); } } // namespace util } // namespace cv #endif // OPENCV_GAPI_UTIL_OPTIONAL_HPP