///\file /****************************************************************************** The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com Copyright(c) 2015 John Wellbelove Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ #ifndef ETL_OPTIONAL_INCLUDED #define ETL_OPTIONAL_INCLUDED #include "platform.h" #include "alignment.h" #include "memory.h" #include "type_traits.h" #include "exception.h" #include "error_handler.h" #include "utility.h" #include "placement_new.h" namespace etl { //***************************************************************************** /// A null option type. ///\ingroup utilities //***************************************************************************** class nullopt_t { public: // Convertible to any type of null non-member pointer. template operator T*() const { return 0; } private: // Can't take address of nullopt. void operator&() const ETL_DELETE; }; //***************************************************************************** /// A null option. ///\ingroup utilities //***************************************************************************** const nullopt_t nullopt = {}; //*************************************************************************** /// Exception for optional. ///\ingroup list //*************************************************************************** class optional_exception : public exception { public: optional_exception(string_type reason_, string_type file_name_, numeric_type line_number_) : exception(reason_, file_name_, line_number_) { } }; //*************************************************************************** /// Invalid exception for optional. ///\ingroup list //*************************************************************************** class optional_invalid : public optional_exception { public: optional_invalid(string_type file_name_, numeric_type line_number_) : optional_exception("optional:invalid", file_name_, line_number_) { } }; //***************************************************************************** // Implementations for fundamental and non fundamental types. //***************************************************************************** namespace private_optional { template ::value> class optional_impl; //***************************************************************************** // Implementation for non fundamental types. //***************************************************************************** template class optional_impl { protected: typedef T value_type; //*************************************************************************** /// Constructor. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl() : storage() { } //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl(etl::nullopt_t) : storage() { } #include "private/diagnostic_uninitialized_push.h" //*************************************************************************** /// Copy constructor. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl(const optional_impl& other) { if (other.has_value()) { storage.construct(other.value()); } } #include "private/diagnostic_pop.h" #if ETL_USING_CPP11 //*************************************************************************** /// Move constructor. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl(optional_impl&& other) { if (other.has_value()) { storage.construct(etl::move(other.value())); } } #endif //*************************************************************************** /// Constructor from value type. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl(const T& value_) { storage.construct(value_); } #if ETL_USING_CPP11 //*************************************************************************** /// Constructor from value type. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl(T&& value_) { storage.construct(etl::move(value_)); } #endif //*************************************************************************** /// Destructor. //*************************************************************************** ETL_CONSTEXPR20_STL ~optional_impl() { storage.destroy(); } //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl& operator =(etl::nullopt_t) { if (has_value()) { storage.destroy(); } return *this; } //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl& operator =(const optional_impl& other) { if (this != &other) { if (other.has_value()) { storage.construct(other.value()); } else { storage.destroy(); } } return *this; } #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl& operator =(optional_impl&& other) { if (this != &other) { if (other.has_value()) { storage.construct(etl::move(other.value())); } else { storage.destroy(); } } return *this; } #endif //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl& operator =(const T& value_) { storage.construct(value_); return *this; } #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** ETL_CONSTEXPR20_STL optional_impl& operator =(T&& value_) { storage.construct(etl::move(value_)); return *this; } #endif public: //*************************************************************************** /// Pointer operator. //*************************************************************************** ETL_CONSTEXPR20_STL T* operator ->() { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return &storage.u.value; } //*************************************************************************** /// Pointer operator. //*************************************************************************** ETL_CONSTEXPR20_STL const T* operator ->() const { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return &storage.u.value; } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR20_STL T& operator *() ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.u.value; } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR20_STL const T& operator *() const ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.u.value; } #if ETL_USING_CPP11 //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR20_STL T&& operator *()&& { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.u.value); } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR20_STL const T&& operator *() const&& { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.u.value); } #endif //*************************************************************************** // Check whether optional contains value //*************************************************************************** ETL_CONSTEXPR20_STL bool has_value() const ETL_NOEXCEPT { return storage.valid; } //*************************************************************************** /// Bool conversion operator. //*************************************************************************** ETL_CONSTEXPR20_STL ETL_EXPLICIT operator bool() const { return has_value(); } //*************************************************************************** /// Get a reference to the value. //*************************************************************************** ETL_CONSTEXPR20_STL T& value() ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.u.value; } //*************************************************************************** /// Get a const reference to the value. //*************************************************************************** ETL_CONSTEXPR20_STL const T& value() const ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.u.value; } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** ETL_CONSTEXPR20_STL T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER { return has_value() ? value() : default_value; } #if ETL_USING_CPP11 //*************************************************************************** /// Get an rvalue reference to the value. //*************************************************************************** ETL_CONSTEXPR20_STL T&& value()&& { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.u.value); } //*************************************************************************** /// Get a const rvalue reference to the value. //*************************************************************************** ETL_CONSTEXPR20_STL const T&& value() const&& { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.u.value); } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** template ETL_CONSTEXPR20_STL etl::enable_if_t::value, T> value_or(U&& default_value) const& { return has_value() ? value() : etl::forward(default_value); } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** template ETL_CONSTEXPR20_STL etl::enable_if_t::value, T> value_or(U&& default_value)&& { return has_value() ? etl::move(value()) : etl::forward(default_value); } #endif //*************************************************************************** /// Swaps this value with another. //*************************************************************************** ETL_CONSTEXPR20_STL void swap(optional_impl& other) { optional_impl temp(*this); *this = other; other = temp; } //*************************************************************************** /// Reset back to invalid. //*************************************************************************** ETL_CONSTEXPR20_STL void reset() { storage.destroy(); } #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_OPTIONAL_FORCE_CPP03_IMPLEMENTATION) //************************************************************************* /// Emplaces a value. ///\param args The arguments to construct with. //************************************************************************* template ETL_CONSTEXPR20_STL void emplace(TArgs&& ... args) { storage.construct(etl::forward(args)...); } #else //************************************************************************* /// Emplaces a value. /// 1 parameter. //************************************************************************* T& emplace() { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.u.value) T(); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 1 parameter. //************************************************************************* template T& emplace(const T1& value1) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.u.value) T(value1); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 2 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.u.value) T(value1, value2); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 3 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2, const T3& value3) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.u.value) T(value1, value2, value3); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 4 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.u.value) T(value1, value2, value3, value4); storage.valid = true; return *p; } #endif private: struct dummy_t {}; //************************************* // The storage for the optional value. //************************************* struct storage_type { //******************************* ETL_CONSTEXPR20_STL storage_type() : u() , valid(false) { } //******************************* ETL_CONSTEXPR20_STL void construct(const T& value_) { if (valid) { etl::destroy_at(&u.value); } etl::construct_at(&u.value, value_); valid = true; } #if ETL_USING_CPP11 //******************************* ETL_CONSTEXPR20_STL void construct(T&& value_) { if (valid) { etl::destroy_at(&u.value); } etl::construct_at(&u.value, etl::move(value_)); valid = true; } //******************************* template ETL_CONSTEXPR20_STL void construct(TArgs&&... args) { if (valid) { etl::destroy_at(&u.value); } etl::construct_at(&u.value, etl::forward(args)...); valid = true; } #endif //******************************* ETL_CONSTEXPR20_STL void destroy() { if (valid) { etl::destroy_at(&u.value); valid = false; } } //******************************* union union_type { ETL_CONSTEXPR20_STL union_type() : dummy() { } ETL_CONSTEXPR20_STL ~union_type() { } dummy_t dummy; T value; } u; bool valid; }; storage_type storage; }; //***************************************************************************** // Implementation for fundamental types. //***************************************************************************** template class optional_impl { protected: typedef T value_type; //*************************************************************************** /// Constructor. //*************************************************************************** ETL_CONSTEXPR14 optional_impl() : storage() { } //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** ETL_CONSTEXPR14 optional_impl(etl::nullopt_t) : storage() { } #include "private/diagnostic_uninitialized_push.h" //*************************************************************************** /// Copy constructor. //*************************************************************************** ETL_CONSTEXPR14 optional_impl(const optional_impl& other) { if (other.has_value()) { storage.construct(other.value()); } } #include "private/diagnostic_pop.h" #if ETL_USING_CPP11 //*************************************************************************** /// Move constructor. //*************************************************************************** ETL_CONSTEXPR14 optional_impl(optional_impl&& other) { if (other.has_value()) { storage.construct(etl::move(other.value())); } } #endif //*************************************************************************** /// Constructor from value type. //*************************************************************************** ETL_CONSTEXPR14 optional_impl(const T& value_) { storage.construct(value_); } #if ETL_USING_CPP11 //*************************************************************************** /// Constructor from value type. //*************************************************************************** ETL_CONSTEXPR14 optional_impl(T&& value_) { storage.construct(etl::move(value_)); } #endif //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** ETL_CONSTEXPR14 optional_impl& operator =(etl::nullopt_t) { if (has_value()) { storage.destroy(); } return *this; } //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR14 optional_impl& operator =(const optional_impl& other) { if (this != &other) { if (other.has_value()) { storage.construct(other.value()); } else { storage.destroy(); } } return *this; } #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from optional_impl. //*************************************************************************** ETL_CONSTEXPR14 optional_impl& operator =(optional_impl&& other) { if (this != &other) { if (other.has_value()) { storage.construct(etl::move(other.value())); } else { storage.destroy(); } } return *this; } #endif //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** ETL_CONSTEXPR14 optional_impl& operator =(const T& value_) { storage.construct(value_); return *this; } #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** ETL_CONSTEXPR14 optional_impl& operator =(T&& value_) { storage.construct(etl::move(value_)); return *this; } #endif public: //*************************************************************************** /// Pointer operator. //*************************************************************************** ETL_CONSTEXPR14 T* operator ->() { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return &storage.value; } //*************************************************************************** /// Pointer operator. //*************************************************************************** ETL_CONSTEXPR14 const T* operator ->() const { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return &storage.value; } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR14 T& operator *() ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.value; } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR14 const T& operator *() const ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.value; } #if ETL_USING_CPP11 //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR14 T&& operator *()&& { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.value); } //*************************************************************************** /// Dereference operator. //*************************************************************************** ETL_CONSTEXPR14 const T&& operator *() const&& { #if ETL_IS_DEBUG_BUILD && !(ETL_USING_CPP20 && ETL_USING_STL) ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.value); } #endif //*************************************************************************** // Check whether optional contains value //*************************************************************************** ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT { return storage.valid; } //*************************************************************************** /// Bool conversion operator. //*************************************************************************** ETL_CONSTEXPR14 ETL_EXPLICIT operator bool() const { return has_value(); } //*************************************************************************** /// Get a reference to the value. //*************************************************************************** ETL_CONSTEXPR14 T& value() ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.value; } //*************************************************************************** /// Get a const reference to the value. //*************************************************************************** ETL_CONSTEXPR14 const T& value() const ETL_LVALUE_REF_QUALIFIER { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return storage.value; } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** ETL_CONSTEXPR14 T value_or(const T& default_value) const ETL_LVALUE_REF_QUALIFIER { return has_value() ? value() : default_value; } #if ETL_USING_CPP11 //*************************************************************************** /// Get an rvalue reference to the value. //*************************************************************************** ETL_CONSTEXPR14 T&& value()&& { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.value); } //*************************************************************************** /// Get a const rvalue reference to the value. //*************************************************************************** ETL_CONSTEXPR14 const T&& value() const&& { #if ETL_IS_DEBUG_BUILD ETL_ASSERT(has_value(), ETL_ERROR(optional_invalid)); #endif return etl::move(storage.value); } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** template ETL_CONSTEXPR14 etl::enable_if_t::value, T> value_or(U&& default_value) const& { return has_value() ? value() : etl::forward(default_value); } //*************************************************************************** /// Gets the value or a default if not valid. //*************************************************************************** template ETL_CONSTEXPR14 etl::enable_if_t::value, T> value_or(U&& default_value)&& { return has_value() ? etl::move(value()) : etl::forward(default_value); } #endif //*************************************************************************** /// Swaps this value with another. //*************************************************************************** ETL_CONSTEXPR14 void swap(optional_impl& other) { optional_impl temp(*this); *this = other; other = temp; } //*************************************************************************** /// Reset back to invalid. //*************************************************************************** ETL_CONSTEXPR14 void reset() { storage.destroy(); } #if ETL_USING_CPP11 && ETL_NOT_USING_STLPORT && !defined(ETL_OPTIONAL_FORCE_CPP03_IMPLEMENTATION) //************************************************************************* /// Emplaces a value. ///\param args The arguments to construct with. //************************************************************************* template ETL_CONSTEXPR14 void emplace(TArgs&& ... args) { storage.construct(etl::forward(args)...); } #else //************************************************************************* /// Emplaces a value. /// 1 parameter. //************************************************************************* T& emplace() { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.value) T(); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 1 parameter. //************************************************************************* template T& emplace(const T1& value1) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.value) T(value1); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 2 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.value) T(value1, value2); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 3 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2, const T3& value3) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.value) T(value1, value2, value3); storage.valid = true; return *p; } //************************************************************************* /// Emplaces a value. /// 4 parameters. //************************************************************************* template T& emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) { if (has_value()) { // Destroy the old one. storage.destroy(); } T* p = ::new (&storage.value) T(value1, value2, value3, value4); storage.valid = true; return *p; } #endif private: //************************************* // The storage for the optional value. //************************************* struct storage_type { //******************************* ETL_CONSTEXPR14 storage_type() : value() , valid(false) { } //******************************* ETL_CONSTEXPR14 void construct(const T& value_) { value = value_; valid = true; } #if ETL_USING_CPP11 //******************************* ETL_CONSTEXPR14 void construct(T&& value_) { value = value_; valid = true; } //******************************* template ETL_CONSTEXPR14 void construct(TArgs&&... args) { value = T(etl::forward(args)...); valid = true; } #endif //******************************* ETL_CONSTEXPR14 void destroy() { valid = false; } T value; bool valid; }; storage_type storage; }; } #define ETL_OPTIONAL_ENABLE_CPP14 typename etl::enable_if< etl::is_pod::value, int>::type = 0 #define ETL_OPTIONAL_ENABLE_CPP20_STL typename etl::enable_if::value, int>::type = 0 #define ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 ETL_CONSTEXPR14 typename etl::enable_if< etl::is_pod::value, bool>::type #define ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL ETL_CONSTEXPR20_STL typename etl::enable_if::value, bool>::type //***************************************************************************** /// An optional type. /// If the optional type is not initialised then a type is not constructed. /// See http://en.cppreference.com/w/cpp/utility/optional ///\tparam T The type to store. ///\ingroup utilities //***************************************************************************** template class optional : public private_optional::optional_impl { private: typedef private_optional::optional_impl impl_t; public: typedef T value_type; #if ETL_USING_CPP11 //*************************************************************************** /// Constructor. //*************************************************************************** template ETL_CONSTEXPR14 optional() : impl_t() { } //*************************************************************************** /// Constructor. //*************************************************************************** template ETL_CONSTEXPR20_STL optional() : impl_t() { } #else optional() : impl_t() { } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** template ETL_CONSTEXPR14 optional(etl::nullopt_t) : impl_t(etl::nullopt) { } //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** template ETL_CONSTEXPR20_STL optional(etl::nullopt_t) : impl_t(etl::nullopt) { } #else //*************************************************************************** /// Constructor with nullopt. //*************************************************************************** optional(etl::nullopt_t) : impl_t(etl::nullopt) { } #endif #include "private/diagnostic_uninitialized_push.h" #if ETL_USING_CPP11 //*************************************************************************** /// Copy constructor. //*************************************************************************** template ETL_CONSTEXPR14 optional(const optional& other) : impl_t(other) { } //*************************************************************************** /// Copy constructor. //*************************************************************************** template ETL_CONSTEXPR20_STL optional(const optional& other) : impl_t(other) { } #else //*************************************************************************** /// Copy constructor. //*************************************************************************** optional(const optional& other) : impl_t(other) { } #endif #include "private/diagnostic_pop.h" #if ETL_USING_CPP11 //*************************************************************************** /// Move constructor. //*************************************************************************** template ETL_CONSTEXPR14 optional(optional&& other) : impl_t(other) { } //*************************************************************************** /// Move constructor. //*************************************************************************** template ETL_CONSTEXPR20_STL optional(optional&& other) : impl_t(other) { } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Construct from value type. //*************************************************************************** template ETL_CONSTEXPR14 optional(const T& value_) : impl_t(value_) { } //*************************************************************************** /// Construct from value type. //*************************************************************************** template ETL_CONSTEXPR20_STL optional(const T& value_) : impl_t(value_) { } #else //*************************************************************************** /// Construct from value type. //*************************************************************************** optional(const T& value_) : impl_t(value_) { } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Move construct from value type. //*************************************************************************** template ETL_CONSTEXPR14 optional(T&& value_) : impl_t(etl::move(value_)) { } //*************************************************************************** /// Move construct from value type. //*************************************************************************** template ETL_CONSTEXPR20_STL optional(T&& value_) : impl_t(etl::move(value_)) { } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** template ETL_CONSTEXPR14 optional& operator =(etl::nullopt_t) { impl_t::operator=(etl::nullopt); return *this; } //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** template ETL_CONSTEXPR20_STL optional& operator =(etl::nullopt_t) { impl_t::operator=(etl::nullopt); return *this; } #else //*************************************************************************** /// Assignment operator from nullopt. //*************************************************************************** optional& operator =(etl::nullopt_t) { impl_t::operator=(etl::nullopt); return *this; } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from optional. //*************************************************************************** template ETL_CONSTEXPR14 optional& operator =(const optional& other) { impl_t::operator=(other); return *this; } //*************************************************************************** /// Assignment operator from optional. //*************************************************************************** template ETL_CONSTEXPR20_STL optional& operator =(const optional& other) { impl_t::operator=(other); return *this; } #else //*************************************************************************** /// Assignment operator from optional. //*************************************************************************** optional& operator =(const optional& other) { impl_t::operator=(other); return *this; } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Move assignment operator from optional. //*************************************************************************** template ETL_CONSTEXPR14 optional& operator =(optional&& other) { impl_t::operator=(etl::move(other)); return *this; } //*************************************************************************** /// Move assignment operator from optional. //*************************************************************************** template ETL_CONSTEXPR20_STL optional& operator =(optional&& other) { impl_t::operator=(etl::move(other)); return *this; } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** template ETL_CONSTEXPR14 optional& operator =(const T& value_) { impl_t::operator=(value_); return *this; } //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** template ETL_CONSTEXPR20_STL optional& operator =(const T& value_) { impl_t::operator=(value_); return *this; } #else //*************************************************************************** /// Assignment operator from value type. //*************************************************************************** optional& operator =(const T& value_) { impl_t::operator=(value_); return *this; } #endif #if ETL_USING_CPP11 //*************************************************************************** /// Move assignment operator from value type. //*************************************************************************** template ETL_CONSTEXPR14 optional& operator =(T&& value_) { impl_t::operator=(etl::move(value_)); return *this; } //*************************************************************************** /// Move assignment operator from value type. //*************************************************************************** template ETL_CONSTEXPR20_STL optional& operator =(T&& value_) { impl_t::operator=(etl::move(value_)); return *this; } #endif }; #include "private/diagnostic_uninitialized_push.h" //*************************************************************************** /// Equality operator. cppreference 1 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator ==(const etl::optional& lhs, const etl::optional& rhs) { if (lhs.has_value() != rhs.has_value()) { return false; } else if (!lhs.has_value() && !rhs.has_value()) { return true; } else { return lhs.value() == rhs.value(); } } //*************************************************************************** /// Equality operator. cppreference 1 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator ==(const etl::optional& lhs, const etl::optional& rhs) { if (lhs.has_value() != rhs.has_value()) { return false; } else if (!lhs.has_value() && !rhs.has_value()) { return true; } else { return lhs.value() == rhs.value(); } } //*************************************************************************** /// Inequality operator. cppreference 2 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator !=(const etl::optional& lhs, const etl::optional& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Inequality operator. cppreference 2 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator !=(const etl::optional& lhs, const etl::optional& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Less than operator. cppreference 3 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <(const etl::optional& lhs, const etl::optional& rhs) { if (!rhs.has_value()) { return false; } else if (!lhs.has_value()) { return true; } else { return lhs.value() < rhs.value(); } } //*************************************************************************** /// Less than operator. cppreference 3 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <(const etl::optional& lhs, const etl::optional& rhs) { if (!rhs.has_value()) { return false; } else if (!lhs.has_value()) { return true; } else { return lhs.value() < rhs.value(); } } //*************************************************************************** /// Less than equal operator. cppreference 4 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <=(const etl::optional& lhs, const etl::optional& rhs) { return !(rhs < lhs); } //*************************************************************************** /// Less than equal operator. cppreference 4 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <=(const etl::optional& lhs, const etl::optional& rhs) { return !(rhs < lhs); } //*************************************************************************** /// greater than operator. cppreference 5 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >(const etl::optional& lhs, const etl::optional& rhs) { return (rhs < lhs); } //*************************************************************************** /// greater than operator. cppreference 5 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >(const etl::optional& lhs, const etl::optional& rhs) { return (rhs < lhs); } //*************************************************************************** /// greater than equal operator. cppreference 6 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >=(const etl::optional& lhs, const etl::optional& rhs) { return !(lhs < rhs); } //*************************************************************************** /// greater than equal operator. cppreference 6 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >=(const etl::optional& lhs, const etl::optional& rhs) { return !(lhs < rhs); } //*************************************************************************** /// Equality operator. cppreference 7 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator ==(const etl::optional& lhs, etl::nullopt_t) { return !lhs.has_value(); } //*************************************************************************** /// Equality operator. cppreference 7 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator ==(const etl::optional& lhs, etl::nullopt_t) { return !lhs.has_value(); } //*************************************************************************** /// Equality operator. cppreference 8 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator ==(etl::nullopt_t, const etl::optional& rhs) { return !rhs.has_value(); } //*************************************************************************** /// Equality operator. cppreference 8 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator ==(etl::nullopt_t, const etl::optional& rhs) { return !rhs.has_value(); } //*************************************************************************** /// Inequality operator. cppreference 9 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator !=(const etl::optional& lhs, etl::nullopt_t) { return !(lhs == etl::nullopt); } //*************************************************************************** /// Inequality operator. cppreference 9 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator !=(const etl::optional& lhs, etl::nullopt_t) { return !(lhs == etl::nullopt); } //*************************************************************************** /// Inequality operator. cppreference 10 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator !=(etl::nullopt_t , const etl::optional& rhs) { return !(etl::nullopt == rhs); } //*************************************************************************** /// Inequality operator. cppreference 10 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator !=(etl::nullopt_t, const etl::optional& rhs) { return !(etl::nullopt == rhs); } //*************************************************************************** /// Less than operator. cppreference 11 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <(const etl::optional&, etl::nullopt_t) { return false; } //*************************************************************************** /// Less than operator. cppreference 11 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <(const etl::optional&, etl::nullopt_t) { return false; } //*************************************************************************** /// Less than operator. cppreference 12 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <(etl::nullopt_t, const etl::optional& rhs) { return rhs.has_value(); } //*************************************************************************** /// Less than operator. cppreference 12 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <(etl::nullopt_t, const etl::optional& rhs) { return rhs.has_value(); } //*************************************************************************** /// Less than equal operator. cppreference 13 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <=(const etl::optional& lhs, etl::nullopt_t) { return !lhs.has_value(); } //*************************************************************************** /// Less than equal operator. cppreference 13 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <=(const etl::optional& lhs, etl::nullopt_t) { return !lhs.has_value(); } //*************************************************************************** /// Less than equal operator. cppreference 14 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <=(etl::nullopt_t, const etl::optional&) { return true; } //*************************************************************************** /// Less than equal operator. cppreference 14 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <=(etl::nullopt_t, const etl::optional&) { return true; } //*************************************************************************** /// Greater than operator. cppreference 15 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >(const etl::optional& lhs, etl::nullopt_t) { return lhs.has_value(); } //*************************************************************************** /// Greater than operator. cppreference 15 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >(const etl::optional& lhs, etl::nullopt_t) { return lhs.has_value(); } //*************************************************************************** /// Greater than operator. cppreference 16 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >(etl::nullopt_t, const etl::optional&) { return false; } //*************************************************************************** /// Greater than operator. cppreference 16 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >(etl::nullopt_t, const etl::optional&) { return false; } //*************************************************************************** /// Greater than equal operator. cppreference 17 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >=(const etl::optional&, etl::nullopt_t) { return true; } //*************************************************************************** /// Greater than equal operator. cppreference 17 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >=(const etl::optional&, etl::nullopt_t) { return true; } //*************************************************************************** /// Greater than equal operator. cppreference 18 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >=(etl::nullopt_t, const etl::optional& rhs) { return !rhs.has_value(); } //*************************************************************************** /// Greater than equal operator. cppreference 18 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >=(etl::nullopt_t, const etl::optional& rhs) { return !rhs.has_value(); } //*************************************************************************** /// Equality operator. cppreference 19 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator ==(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() == rhs : false; } //*************************************************************************** /// Equality operator. cppreference 19 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator ==(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() == rhs : false; } //*************************************************************************** /// Inequality operator. cppreference 21 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator !=(const etl::optional& lhs, const U& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Inequality operator. cppreference 21 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator !=(const etl::optional& lhs, const U& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Equality operator. cppreference 20 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator ==(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? rhs.value() == lhs : false; } //*************************************************************************** /// Equality operator. cppreference 20 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator ==(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? rhs.value() == lhs : false; } //*************************************************************************** /// Inequality operator. cppreference 22 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator !=(const U& lhs, const etl::optional& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Inequality operator. cppreference 22 //************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator !=(const U& lhs, const etl::optional& rhs) { return !(lhs == rhs); } //*************************************************************************** /// Less than operator. cppreference 23 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() < rhs : true; } //*************************************************************************** /// Less than operator. cppreference 23 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() < rhs : true; } //*************************************************************************** /// Less than operator. cppreference 24 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs < rhs.value() : false; } //*************************************************************************** /// Less than operator. cppreference 24 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs < rhs.value() : false; } //*************************************************************************** /// Less than equal operator. cppreference 25 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <=(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() <= rhs : true; } //*************************************************************************** /// Less than equal operator. cppreference 25 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <=(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() <= rhs : true; } //*************************************************************************** /// Less than equal operator. cppreference 26 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator <=(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs <= rhs.value() : false; } //*************************************************************************** /// Less than equal operator. cppreference 26 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator <=(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs <= rhs.value() : false; } //*************************************************************************** /// Greater than operator. cppreference 27 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() > rhs : false; } //*************************************************************************** /// Greater than operator. cppreference 27 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() > rhs : false; } //*************************************************************************** /// Greater than operator. cppreference 28 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs > rhs.value() : true; } //*************************************************************************** /// Greater than operator. cppreference 28 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs > rhs.value() : true; } //*************************************************************************** /// Greater than equal operator. cppreference 29 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >=(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() >= rhs : false; } //*************************************************************************** /// Greater than equal operator. cppreference 29 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >=(const etl::optional& lhs, const U& rhs) { return lhs.has_value() ? lhs.value() >= rhs : false; } //*************************************************************************** /// Greater than equal operator. cppreference 30 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP14 operator >=(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs >= rhs.value() : true; } //*************************************************************************** /// Greater than equal operator. cppreference 30 //*************************************************************************** template ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL operator >=(const U& lhs, const etl::optional& rhs) { return rhs.has_value() ? lhs >= rhs.value() : true; } #include "private/diagnostic_pop.h" //*************************************************************************** /// Make an optional. //*************************************************************************** template ETL_CONSTEXPR20_STL etl::optional::type> make_optional(T& value) { return etl::optional::type>(value); } //*************************************************************************** /// Template deduction guides. //*************************************************************************** #if ETL_CPP17_SUPPORTED template optional(T) -> optional; #endif } //************************************************************************* /// Swaps the values. //************************************************************************* template ETL_CONSTEXPR20_STL void swap(etl::optional& lhs, etl::optional& rhs) { lhs.swap(rhs); } #undef ETL_OPTIONAL_ENABLE_CPP14 #undef ETL_OPTIONAL_ENABLE_CPP20_STL #undef ETL_OPTIONAL_ENABLE_CONSTEXPR_BOOL_RETURN_CPP20_STL #undef ETL_OPTIONAL_ENABLE_COMSTEXPR_BOOL_RETURN_CPP20_STL #endif