From b3deaa6761d4e1090f64944ae29e5015974b0815 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 24 Sep 2022 13:12:18 +0100 Subject: [PATCH] Added etl::npos Added specialisation of etl::optional for POD --- include/etl/integral_limits.h | 2 + include/etl/optional.h | 392 +++++++++++++++++++++++++++++++--- 2 files changed, 360 insertions(+), 34 deletions(-) diff --git a/include/etl/integral_limits.h b/include/etl/integral_limits.h index ab4884ef..a93f6c88 100644 --- a/include/etl/integral_limits.h +++ b/include/etl/integral_limits.h @@ -215,6 +215,8 @@ namespace etl static ETL_CONSTANT int bits = CHAR_BIT * (sizeof(unsigned long long) / sizeof(char)); static ETL_CONSTANT bool is_signed = etl::is_signed::value; }; + + static ETL_CONSTANT size_t npos = etl::integral_limits::max; } #include "private/minmax_pop.h" diff --git a/include/etl/optional.h b/include/etl/optional.h index b4c97792..16574a84 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -103,8 +103,14 @@ namespace etl ///\tparam The type to store. ///\ingroup utilities //***************************************************************************** + template ::value> + class optional; + + //***************************************************************************** + /// For non POD types. + //***************************************************************************** template - class optional + class optional { public: @@ -359,7 +365,6 @@ namespace etl return valid; } - //*************************************************************************** /// Get a reference to the value. //*************************************************************************** @@ -507,11 +512,322 @@ namespace etl bool valid; }; + //***************************************************************************** + /// For POD types. + //***************************************************************************** + template + class optional + { + public: + + //*************************************************************************** + /// Constructor. + //*************************************************************************** + ETL_CONSTEXPR14 optional() + : storage() + , valid(false) + { + } + + //*************************************************************************** + /// Constructor with nullopt. + //*************************************************************************** + ETL_CONSTEXPR14 optional(etl::nullopt_t) + : storage() + , valid(false) + { + } + + //*************************************************************************** + /// Copy constructor. + //*************************************************************************** + ETL_CONSTEXPR14 optional(const optional& other) + : valid(bool(other)) + , storage(other.storage) + { + } + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Move constructor. + //*************************************************************************** + ETL_CONSTEXPR14 optional(optional&& other) + : valid(bool(other)) + , storage(etl::move(other.storage)) + { + } +#endif + + //*************************************************************************** + /// Constructor from value type. + //*************************************************************************** + ETL_CONSTEXPR14 optional(const T& value_) + : storage(value_) + , valid(true) + { + } + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Constructor from value type. + //*************************************************************************** + ETL_CONSTEXPR14 optional(T&& value_) + : storage(etl::move(value_)) + , valid(true) + { + } +#endif + + //*************************************************************************** + /// Assignment operator from nullopt. + //*************************************************************************** + ETL_CONSTEXPR14 optional& operator =(etl::nullopt_t) + { + return *this; + } + + //*************************************************************************** + /// Assignment operator from optional. + //*************************************************************************** + ETL_CONSTEXPR14 optional& operator =(const optional& other) + { + if (this != &other) + { + storage = other.storage; + valid = other.valid; + } + + return *this; + } + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Assignment operator from optional. + //*************************************************************************** + ETL_CONSTEXPR14 optional& operator =(optional&& other) + { + if (this != &other) + { + storage = etl::move(other.storage); + valid = true; + } + + return *this; + } +#endif + + //*************************************************************************** + /// Assignment operator from value type. + //*************************************************************************** + ETL_CONSTEXPR14 optional& operator =(const T& value_) + { + storage = value_; + valid = true; + + return *this; + } + +#if ETL_USING_CPP11 + //*************************************************************************** + /// Assignment operator from value type. + //*************************************************************************** + ETL_CONSTEXPR14 optional& operator =(T&& value_) + { + storage = etl::move(value_); + valid = true; + + return *this; + } +#endif + + //*************************************************************************** + /// Pointer operator. + //*************************************************************************** + ETL_CONSTEXPR14 T* operator ->() + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return &storage; + } + + //*************************************************************************** + /// Pointer operator. + //*************************************************************************** + ETL_CONSTEXPR14 const T* operator ->() const + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return &storage; + } + + //*************************************************************************** + /// Dereference operator. + //*************************************************************************** + ETL_CONSTEXPR14 T& operator *() + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return storage; + } + + //*************************************************************************** + /// Dereference operator. + //*************************************************************************** + ETL_CONSTEXPR14 const T& operator *() const + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return storage; + } + + //*************************************************************************** + /// Bool conversion operator. + //*************************************************************************** + ETL_CONSTEXPR14 operator bool() const + { + return valid; + } + + //*************************************************************************** + // Check whether optional contains value + //*************************************************************************** + ETL_CONSTEXPR14 bool has_value() const ETL_NOEXCEPT + { + return valid; + } + + //*************************************************************************** + /// Get a reference to the value. + //*************************************************************************** + ETL_CONSTEXPR14 T& value() + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return storage; + } + + //*************************************************************************** + /// Get a const reference to the value. + //*************************************************************************** + ETL_CONSTEXPR14 const T& value() const + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(optional_invalid)); +#endif + + return storage; + } + + //*************************************************************************** + /// Gets the value or a default if no valid. + //*************************************************************************** + ETL_CONSTEXPR14 T value_or(T default_value) const + { + return valid ? value() : default_value; + } + + //*************************************************************************** + /// Swaps this value with another. + //*************************************************************************** + ETL_CONSTEXPR14 void swap(optional& other) + { + optional temp(*this); + *this = other; + other = temp; + } + + //*************************************************************************** + /// Reset back to invalid. + //*************************************************************************** + ETL_CONSTEXPR14 void reset() + { + valid = false; + } + +#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(Args && ... args) + { + if (valid) + { + // Destroy the old one. + storage.template get_reference().~T(); + } + + storage = T(ETL_OR_STD::forward(args)...); + valid = true; + } +#else + //************************************************************************* + /// Emplaces a value. + /// 1 parameter. + //************************************************************************* + template + void emplace(const T1& value1) + { + storage = value1; + valid = true; + } + + //************************************************************************* + /// Emplaces a value. + /// 2 parameters. + //************************************************************************* + template + void emplace(const T1& value1, const T2& value2) + { + storage = T(value1, value2); + valid = true; + } + + //************************************************************************* + /// Emplaces a value. + /// 3 parameters. + //************************************************************************* + template + void emplace(const T1& value1, const T2& value2, const T3& value3) + { + storage = T(value1, value2, value3); + valid = true; + } + + //************************************************************************* + /// Emplaces a value. + /// 4 parameters. + //************************************************************************* + template + void emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + storage = T(value1, value2, value3, value4); + valid = true; + } +#endif + + private: + + T storage; + bool valid; + }; + //*************************************************************************** /// Equality operator. cppreference 1 //*************************************************************************** template - bool operator ==(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator ==(const etl::optional& lhs, const etl::optional& rhs) { if (bool(lhs) != bool(rhs)) { @@ -531,7 +847,7 @@ namespace etl /// Equality operator. cppreference 2 //*************************************************************************** template - bool operator !=(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator !=(const etl::optional& lhs, const etl::optional& rhs) { return !(lhs == rhs); } @@ -540,7 +856,7 @@ namespace etl /// Less than operator. cppreference 3 //*************************************************************************** template - bool operator <(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator <(const etl::optional& lhs, const etl::optional& rhs) { if (!bool(rhs)) { @@ -560,7 +876,7 @@ namespace etl /// Less than equal operator. cppreference 4 //*************************************************************************** template - bool operator <=(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator <=(const etl::optional& lhs, const etl::optional& rhs) { if (!bool(lhs)) { @@ -580,7 +896,7 @@ namespace etl /// greater than operator. cppreference 5 //*************************************************************************** template - bool operator >(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator >(const etl::optional& lhs, const etl::optional& rhs) { if (!bool(lhs)) { @@ -600,7 +916,7 @@ namespace etl /// greater than equal operator. cppreference 6 //*************************************************************************** template - bool operator >=(const etl::optional& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator >=(const etl::optional& lhs, const etl::optional& rhs) { if (!bool(rhs)) { @@ -620,7 +936,7 @@ namespace etl /// Equality operator. cppreference 7 //*************************************************************************** template - bool operator ==(const etl::optional& lhs, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator ==(const etl::optional& lhs, etl::nullopt_t) { return !bool(lhs); } @@ -629,7 +945,7 @@ namespace etl /// Equality operator. cppreference 8 //*************************************************************************** template - bool operator ==(etl::nullopt_t, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator ==(etl::nullopt_t, const etl::optional& rhs) { return !bool(rhs); } @@ -638,7 +954,7 @@ namespace etl /// Inequality operator. cppreference 9 //*************************************************************************** template - bool operator !=(const etl::optional& lhs, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator !=(const etl::optional& lhs, etl::nullopt_t) { return !(lhs == etl::nullopt); } @@ -647,7 +963,7 @@ namespace etl /// Inequality operator. cppreference 10 //*************************************************************************** template - bool operator !=(etl::nullopt_t , const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator !=(etl::nullopt_t , const etl::optional& rhs) { return !(etl::nullopt == rhs); } @@ -656,7 +972,7 @@ namespace etl /// Less than operator. cppreference 11 //*************************************************************************** template - bool operator <(const etl::optional&, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator <(const etl::optional&, etl::nullopt_t) { return false; } @@ -665,7 +981,7 @@ namespace etl /// Less than operator. cppreference 12 //*************************************************************************** template - bool operator <(etl::nullopt_t, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator <(etl::nullopt_t, const etl::optional& rhs) { return bool(rhs); } @@ -674,7 +990,7 @@ namespace etl /// Less than equal operator. cppreference 13 //*************************************************************************** template - bool operator <=(const etl::optional& lhs, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator <=(const etl::optional& lhs, etl::nullopt_t) { return !bool(lhs); } @@ -683,7 +999,7 @@ namespace etl /// Less than equal operator. cppreference 14 //*************************************************************************** template - bool operator <=(etl::nullopt_t, const etl::optional&) + ETL_CONSTEXPR14 bool operator <=(etl::nullopt_t, const etl::optional&) { return true; } @@ -692,7 +1008,7 @@ namespace etl /// Greater than operator. cppreference 15 //*************************************************************************** template - bool operator >(const etl::optional& lhs, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator >(const etl::optional& lhs, etl::nullopt_t) { return bool(lhs); } @@ -701,7 +1017,7 @@ namespace etl /// Greater than operator. cppreference 16 //*************************************************************************** template - bool operator >(etl::nullopt_t, const etl::optional&) + ETL_CONSTEXPR14 bool operator >(etl::nullopt_t, const etl::optional&) { return false; } @@ -710,7 +1026,7 @@ namespace etl /// Greater than equal operator. cppreference 17 //*************************************************************************** template - bool operator >=(const etl::optional&, etl::nullopt_t) + ETL_CONSTEXPR14 bool operator >=(const etl::optional&, etl::nullopt_t) { return true; } @@ -719,7 +1035,7 @@ namespace etl /// Greater than equal operator. cppreference 18 //*************************************************************************** template - bool operator >=(etl::nullopt_t, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator >=(etl::nullopt_t, const etl::optional& rhs) { return !bool(rhs); } @@ -728,7 +1044,7 @@ namespace etl /// Equality operator. cppreference 19 //************************************************************************** template - bool operator ==(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator ==(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() == rhs : false; } @@ -737,7 +1053,7 @@ namespace etl /// Inequality operator. cppreference 21 //************************************************************************** template - bool operator !=(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator !=(const etl::optional& lhs, const U& rhs) { return !(lhs == rhs); } @@ -746,7 +1062,7 @@ namespace etl /// Equality operator. cppreference 20 //************************************************************************** template - bool operator ==(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator ==(const U& lhs, const etl::optional& rhs) { return bool(rhs) ? rhs.value() == lhs : false; } @@ -755,7 +1071,7 @@ namespace etl /// Inequality operator. cppreference 22 //************************************************************************** template - bool operator !=(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator !=(const U& lhs, const etl::optional& rhs) { return !(lhs == rhs); } @@ -764,7 +1080,7 @@ namespace etl /// Less than operator. cppreference 23 //*************************************************************************** template - bool operator <(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator <(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() < rhs : true; } @@ -773,7 +1089,7 @@ namespace etl /// Less than operator. cppreference 24 //*************************************************************************** template - bool operator <(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator <(const U& lhs, const etl::optional& rhs) { return bool(rhs) ? lhs < rhs.value() : false; } @@ -782,7 +1098,7 @@ namespace etl /// Less than equal operator. cppreference 25 //*************************************************************************** template - bool operator <=(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator <=(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() <= rhs : true; } @@ -791,7 +1107,7 @@ namespace etl /// Less than equal operator. cppreference 26 //*************************************************************************** template - bool operator <=(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator <=(const U& lhs, const etl::optional& rhs) { return bool(rhs) ? lhs <= rhs.value() : false; } @@ -800,7 +1116,7 @@ namespace etl /// Greater than operator. cppreference 27 //*************************************************************************** template - bool operator >(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator >(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() > rhs : false; } @@ -809,7 +1125,7 @@ namespace etl /// Greater than operator. cppreference 28 //*************************************************************************** template - bool operator >(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator >(const U& lhs, const etl::optional& rhs) { return bool(rhs) ? lhs > rhs.value() : true; } @@ -818,7 +1134,7 @@ namespace etl /// Greater than equal operator. cppreference 29 //*************************************************************************** template - bool operator >=(const etl::optional& lhs, const U& rhs) + ETL_CONSTEXPR14 bool operator >=(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() >= rhs : false; } @@ -827,7 +1143,7 @@ namespace etl /// Greater than equal operator. cppreference 30 //*************************************************************************** template - bool operator >=(const U& lhs, const etl::optional& rhs) + ETL_CONSTEXPR14 bool operator >=(const U& lhs, const etl::optional& rhs) { return bool(rhs) ? lhs >= rhs.value() : true; } @@ -836,17 +1152,25 @@ namespace etl /// Make an optional. //*************************************************************************** template - etl::optional::type> make_optional(T& value) + ETL_CONSTEXPR14 etl::optional::type> make_optional(T& value) { return etl::optional::type>(value); } + + //*************************************************************************** + /// Template deduction guides. + //*************************************************************************** +#if ETL_CPP17_SUPPORTED + template + etl::optional(T) -> etl::optional; +#endif } //************************************************************************* /// Swaps the values. //************************************************************************* template -void swap(etl::optional& lhs, etl::optional& rhs) +ETL_CONSTEXPR14 void swap(etl::optional& lhs, etl::optional& rhs) { lhs.swap(rhs); }