diff --git a/.gitignore b/.gitignore index f44872fb..d9577b4c 100644 --- a/.gitignore +++ b/.gitignore @@ -363,8 +363,8 @@ examples/ArmTimerCallbacks - C++/ArmTimerCallbacks.uvoptx test/vs2022/.vs test/vs2022/random_clcg.csv test/vs2022/random_hash.csv -test/vs2022/random_lcg.csv test/vs2022/random_lsfr.csv +test/vs2022/random_lcg.csv test/vs2022/random_mwc.csv test/vs2022/random_pcg.csv test/vs2022/random_xorshift.csv diff --git a/include/etl/expected.h b/include/etl/expected.h index 9ca6d03f..013d97d2 100644 --- a/include/etl/expected.h +++ b/include/etl/expected.h @@ -31,12 +31,59 @@ SOFTWARE. #ifndef ETL_EXPECTED_INCLUDED #define ETL_EXPECTED_INCLUDED +///\defgroup expected expected +///\ingroup utilities #include "platform.h" -#include "type_traits.h" +#include "exception.h" +#include "error_handler.h" #include "utility.h" +#include "variant.h" namespace etl { + //*************************************************************************** + /// Base exception for et::expected + //*************************************************************************** + class expected_exception : public etl::exception + { + public: + + expected_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// expected_invalid + //*************************************************************************** + template + class expected_invalid; + + //******************************************* + template<> + class expected_invalid : public etl::expected_exception + { + public: + + expected_invalid(string_type file_name_, numeric_type line_number_) + : expected_exception(ETL_ERROR_TEXT("expected:invalid", ETL_EXPECTED_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + //******************************************* + template + class expected_invalid : etl::expected_invalid + { + public: + + expected_invalid(string_type file_name_, numeric_type line_number_) + : expected_invalid(file_name_, line_number_) + { + } + }; + //*************************************************************************** /// Unexpected type. /// etl::unexpected represents an unexpected value stored in etl::expected. @@ -46,10 +93,12 @@ namespace etl { public: + typedef TError error_type; + //******************************************* /// Copy constructor. //******************************************* - ETL_CONSTEXPR14 unexpected(const unexpected& other) + ETL_CONSTEXPR unexpected(const unexpected& other) : error_value(other.error_value) { } @@ -64,23 +113,24 @@ namespace etl } #endif -#if ETL_USING_CPP11 +#if ETL_CPP11_SUPPORTED //******************************************* /// Construct from argument. //******************************************* - template ::type, etl::unexpected>::value && + template ::type, unexpected>::value && !etl::is_same::type, etl::in_place_t>::value, int>::type> constexpr explicit unexpected(TErr&& e) : error_value(etl::forward(e)) { } + #else //******************************************* /// Construct from argument. //******************************************* template - explicit unexpected(const TErr& e, typename etl::enable_if::type, etl::unexpected >::value && - !etl::is_same::type, etl::in_place_t>::value, int>::type = 0) + explicit unexpected(const TErr& e, typename = typename etl::enable_if::type, unexpected>::value && + !etl::is_same::type, etl::in_place_t>::value, int>::type = 0) : error_value(e) { } @@ -112,10 +162,11 @@ namespace etl /// Assign from etl::unexpected. //******************************************* ETL_CONSTEXPR14 - etl::unexpected& operator =(const etl::unexpected& rhs) + etl::unexpected& operator =(const etl::unexpected& rhs) { - error_value = rhs.error_value; + ETL_STATIC_ASSERT(etl::is_copy_constructible::value, "Error not copy assignable"); + error_value = rhs.error_value; return *this; } @@ -124,10 +175,11 @@ namespace etl /// Move assign from etl::unexpected. //******************************************* ETL_CONSTEXPR14 - etl::unexpected& operator =(etl::unexpected&& rhs) + etl::unexpected& operator =(etl::unexpected&& rhs) { - error_value = etl::move(rhs.error_value); + ETL_STATIC_ASSERT(etl::is_move_constructible::value, "Error not move assignable"); + error_value = etl::move(rhs.error_value); return *this; } #endif @@ -136,7 +188,7 @@ namespace etl //******************************************* /// Get the error. //******************************************* - constexpr const TError& error() const& noexcept + constexpr TError& error() & noexcept { return error_value; } @@ -144,16 +196,7 @@ namespace etl //******************************************* /// Get the error. //******************************************* - constexpr const TError&& error() const&& noexcept - { - return etl::move(error_value); - } - -#if ETL_USING_CPP14 - //******************************************* - /// Get the error. - //******************************************* - constexpr TError& error() & noexcept + constexpr const TError& error() const& noexcept { return error_value; } @@ -165,24 +208,14 @@ namespace etl { return etl::move(error_value); } -#else - //******************************************* - /// Get the error. - //******************************************* - TError& error() & noexcept - { - return error_value; - } //******************************************* /// Get the error. //******************************************* - TError&& error() && noexcept + constexpr TError&& error() const&& noexcept { return etl::move(error_value); } -#endif - #else //******************************************* /// Get the error. @@ -208,10 +241,589 @@ namespace etl TError error_value; }; + //***************************************************************************** + /// unexpect_t + //***************************************************************************** + struct unexpect_t + { + ETL_CONSTEXPR14 explicit unexpect_t() + { + } + }; + #if ETL_USING_CPP17 - template - unexpected(TError) -> unexpected; + inline constexpr unexpect_t unexpect{}; +#else + static const unexpect_t unexpect; #endif + + //***************************************************************************** + /// Expected type. + //***************************************************************************** + template + class expected + { + public: + + typedef etl::expected this_type; + typedef TValue value_type; + typedef TError error_type; + typedef etl::unexpected unexpected_type; + + template + using rebind = expected; + + //******************************************* + /// Default constructor + //******************************************* + ETL_CONSTEXPR14 expected() ETL_NOEXCEPT + : storage(etl::in_place_index, value_type()) + { + } + + //******************************************* + /// Constructor + //******************************************* + ETL_CONSTEXPR14 expected(const value_type& value_) ETL_NOEXCEPT + : storage(etl::in_place_index, value_) + { + } + + //******************************************* + /// Constructor + //******************************************* + ETL_CONSTEXPR14 expected(value_type&& value_) ETL_NOEXCEPT + : storage(etl::in_place_index, etl::move(value_)) + { + } + + //******************************************* + /// Copy constructor + //******************************************* + ETL_CONSTEXPR14 expected(const expected& other) ETL_NOEXCEPT + : storage(other.storage) + { + } + + //******************************************* + /// Move constructor + //******************************************* + ETL_CONSTEXPR14 expected(expected&& other) ETL_NOEXCEPT + : storage(etl::move(other.storage)) + { + } + + //******************************************* + /// Copy construct from unexpected type. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(const etl::unexpected& ue) + : storage(etl::in_place_index, ue.error()) + { + } + + //******************************************* + /// Move construct from unexpected type. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(etl::unexpected&& ue) + : storage(etl::in_place_index, etl::move(ue.error())) + { + } + + //******************************************* + /// Construct with default value type. + //******************************************* + ETL_CONSTEXPR14 explicit expected(etl::in_place_t) ETL_NOEXCEPT + : storage(value_type()) + { + } + + //******************************************* + /// Construct value type from arguments. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(etl::in_place_t, Args&&... args) + : storage(etl::forward(args)...) + { + } + + //******************************************* + /// Construct value type from initializser_list and arguments. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(etl::in_place_t, std::initializer_list il, Args&&... args) + : storage(il, etl::forward(args)...) + { + } + + //******************************************* + /// Construct error type from arguments. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, Args&&... args) + : storage(error_type(etl::forward(args)...)) + { + } + + //******************************************* + /// Construct error type from initializser_list and arguments. + //******************************************* + template + ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, std::initializer_list il, Args&&... args) + : storage(error_type(il, etl::forward(args)...)) + { + } + + //******************************************* + /// + //******************************************* + this_type& operator =(const this_type& other) + { + ETL_STATIC_ASSERT(etl::is_copy_constructible::value && etl::is_copy_constructible::value, "Not copy assignable"); + + storage = other.storage; + + return *this; + } + + //******************************************* + /// + //******************************************* + this_type& operator =(this_type&& other) + { + ETL_STATIC_ASSERT(etl::is_move_constructible::value && etl::is_move_constructible::value, "Not move assignable"); + + storage = etl::move(other.storage); + return *this; + } + + //******************************************* + /// Copy assign from value + //******************************************* + expected& operator =(const value_type& value) + { + ETL_STATIC_ASSERT(etl::is_copy_constructible::value, "Value not copy assignable"); + + storage.emplace(value); + return *this; + } + + //******************************************* + /// Move assign from value + //******************************************* + expected& operator =(value_type&& value) + { + ETL_STATIC_ASSERT(etl::is_move_constructible::value, "Value not move assignable"); + + storage.emplace(etl::move(value)); + return *this; + } + + //******************************************* + /// Copy assign from error + //******************************************* + expected& operator =(const unexpected_type& error) + { + ETL_STATIC_ASSERT(etl::is_copy_constructible::value, "Error not copy assignable"); + + storage.emplace(error); + return *this; + } + + //******************************************* + /// Move assign from error + //******************************************* + expected& operator =(unexpected_type&& error) + { + ETL_STATIC_ASSERT(etl::is_move_constructible::value, "Error not move assignable"); + + storage.emplace(etl::move(error)); + return *this; + } + + //******************************************* + /// + //******************************************* + ETL_CONSTEXPR14 value_type& value()& + { + return etl::get(storage); + } + + //******************************************* + /// + //******************************************* + ETL_CONSTEXPR14 const value_type& value() const& + { + return etl::get(storage); + } + + //******************************************* + /// + //******************************************* + ETL_CONSTEXPR14 value_type&& value()&& + { + return etl::move(etl::get(storage)); + } + + //******************************************* + /// + //******************************************* + ETL_CONSTEXPR14 const value_type&& value() const&& + { + return etl::move(etl::get(storage)); + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool has_value() const + { + return (storage.index() == Value_Type); + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + operator bool() const + { + return has_value(); + } + + //******************************************* + /// + //******************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + value_type value_or(U&& default_value) const& + { + if (has_value()) + { + return value(); + } + else + { + return default_value; + } + } + + //******************************************* + /// + //******************************************* + template + ETL_NODISCARD + ETL_CONSTEXPR14 + value_type value_or(U&& default_value)&& + { + if (has_value()) + { + return etl::move(value()); + } + else + { + return etl::move(default_value); + } + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + error_type& error()& ETL_NOEXCEPT + { + return etl::get(storage); + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const error_type& error() const& ETL_NOEXCEPT + { + return etl::get(storage); + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + error_type&& error() && ETL_NOEXCEPT + { + return etl::move(etl::get(storage)); + } + + //******************************************* + /// + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const error_type&& error() const&& ETL_NOEXCEPT + { + return etl::move(etl::get(storage)); + } + + //******************************************* + /// + //******************************************* + template + ETL_CONSTEXPR14 value_type& emplace(Args&&... args) ETL_NOEXCEPT + { + storage.emplace(args...); + } + + //******************************************* + /// + //******************************************* + template + ETL_CONSTEXPR14 value_type& emplace(std::initializer_list& il, Args&&... args) ETL_NOEXCEPT + { + storage.emplace(il, args...); + } + + //******************************************* + /// + //******************************************* + value_type* operator ->() + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(expected_invalid)); +#endif + + return etl::addressof(storage.get()); + } + + //******************************************* + /// + //******************************************* + const value_type* operator ->() const + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(expected_invalid)); +#endif + + return etl::addressof(storage.get()); + } + + //******************************************* + /// + //******************************************* + value_type& operator *() + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(expected_invalid)); +#endif + + return storage.get(); + } + + //******************************************* + /// + //******************************************* + const value_type& operator *() const + { +#if ETL_IS_DEBUG_BUILD + ETL_ASSERT(valid, ETL_ERROR(expected_invalid)); +#endif + + return storage.get(); + } + + private: + + enum + { + Uninitialised, + Value_Type, + Error_Type + }; + + using storage_type = etl::variant; + storage_type storage; + }; + + //***************************************************************************** + /// Specialisation for void value type. + //***************************************************************************** + template + class expected + { + public: + + typedef etl::expected this_type; + typedef void value_type; + typedef TError error_type; + typedef etl::unexpected unexpected_type; + + //******************************************* + /// Default constructor + //******************************************* + ETL_CONSTEXPR14 + expected() + { + } + + //******************************************* + /// Copy construct from unexpected + //******************************************* + ETL_CONSTEXPR14 + expected(const unexpected_type& ue_) + : storage(ue_.error()) + { + } + + //******************************************* + /// Move construct from unexpected + //******************************************* + ETL_CONSTEXPR14 + expected(unexpected_type&& ue_) + : storage(etl::move(ue_.error())) + { + } + + //******************************************* + /// Copy construct + //******************************************* + ETL_CONSTEXPR14 + expected(const this_type& other) + : storage(other.storage) + { + } + + //******************************************* + /// Move construct + //******************************************* + ETL_CONSTEXPR14 + expected(this_type&& other) + : storage(etl::move(other.storage)) + { + } + + //******************************************* + /// Copy assign + //******************************************* + this_type& operator =(const this_type& other) + { + ETL_STATIC_ASSERT(etl::is_copy_constructible::value, "Not copy assignable"); + + storage = other.storage; + return *this; + } + + //******************************************* + /// Move assign + //******************************************* + this_type& operator =(this_type&& other) + { + ETL_STATIC_ASSERT(etl::is_move_constructible::value, "Not move assignable"); + + storage = etl::move(other.storage); + return *this; + } + + //******************************************* + /// Copy assign from error + //******************************************* + expected& operator =(const unexpected_type& error) + { + ETL_STATIC_ASSERT(etl::is_copy_constructible::value, "Error not copy assignable"); + + storage.emplace(error); + return *this; + } + + //******************************************* + /// Move assign from error + //******************************************* + expected& operator =(unexpected_type&& error) + { + ETL_STATIC_ASSERT(etl::is_move_constructible::value, "Error not move assignable"); + + storage.emplace(etl::move(error)); + return *this; + } + + //******************************************* + /// Returns true if expected has a value + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + bool has_value() const + { + return (storage.index() != Error_Type); + } + + //******************************************* + /// Returns true if expected has a value + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + operator bool() const + { + return has_value(); + } + + //******************************************* + /// Returns the error + /// Undefined behaviour if an error has not been set. + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + error_type& error()& ETL_NOEXCEPT + { + return etl::get(storage); + } + + //******************************************* + /// Returns the error + /// Undefined behaviour if an error has not been set. + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const error_type& error() const& ETL_NOEXCEPT + { + return etl::get(storage); + } + + //******************************************* + /// Returns the error + /// Undefined behaviour if an error has not been set. + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + error_type&& error() && ETL_NOEXCEPT + { + return etl::move(etl::get(storage)); + } + + //******************************************* + /// Returns the error + /// Undefined behaviour if an error has not been set. + //******************************************* + ETL_NODISCARD + ETL_CONSTEXPR14 + const error_type&& error() const&& ETL_NOEXCEPT + { + return etl::move(etl::get(storage)); + } + + private: + + enum + { + Uninitialised, + Error_Type + }; + + etl::variant storage; + }; } //******************************************* @@ -234,20 +846,5 @@ void swap(etl::unexpected& lhs, etl::unexpected& rhs) lhs.swap(rhs); } -//***************************************************************************** -/// unexpect_t -//***************************************************************************** -struct unexpect_t -{ - ETL_CONSTEXPR14 explicit unexpect_t() - { - } -}; - -#if ETL_CPP17_SUPPORTED -inline constexpr unexpect_t unexpect{}; -#else -static const unexpect_t unexpect; #endif -#endif diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index 7d6a0e1a..b0500c48 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -100,5 +100,5 @@ SOFTWARE. #define ETL_BIP_BUFFER_SPSC_ATOMIC_FILE_ID "67" #define ETL_REFERENCE_COUNTED_OBJECT_FILE_ID "68" #define ETL_TO_ARITHMETIC_FILE_ID "69" - +#define ETL_EXPECTED_FILE_ID "70" #endif diff --git a/include/etl/optional.h b/include/etl/optional.h index bf5d791a..ebcb52a1 100644 --- a/include/etl/optional.h +++ b/include/etl/optional.h @@ -91,7 +91,7 @@ namespace etl public: optional_invalid(string_type file_name_, numeric_type line_number_) - : optional_exception("optional: invalid", file_name_, line_number_) + : optional_exception("optional:invalid", file_name_, line_number_) { } }; @@ -100,7 +100,7 @@ namespace etl /// 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 The type to store. + ///\tparam T The type to store. ///\ingroup utilities //***************************************************************************** template ::value> @@ -521,6 +521,8 @@ namespace etl //***************************************************************************** /// For POD types. + ///\tparam T The type to store. + ///\ingroup utilities //***************************************************************************** template class optional diff --git a/include/etl/private/variant_variadic.h b/include/etl/private/variant_variadic.h index fe003364..5d344b5c 100644 --- a/include/etl/private/variant_variadic.h +++ b/include/etl/private/variant_variadic.h @@ -227,7 +227,7 @@ namespace etl default: { // This should never occur. - #if defined(ETL_IN_UNIT_TEST) + #if defined(ETL_DEBUG) assert(false); #endif break; diff --git a/include/etl/result.h b/include/etl/result.h index 95d0fc0c..266cf7c8 100644 --- a/include/etl/result.h +++ b/include/etl/result.h @@ -50,10 +50,13 @@ namespace etl /// Result type. //***************************************************************************** template - class result + class ETL_DEPRECATED result { public: + typedef TValue value_type; + typedef TError error_type; + //******************************************* /// Cannot be default constructed //******************************************* @@ -67,6 +70,7 @@ namespace etl { } +#if ETL_CPP11_SUPPORTED //******************************************* /// Move constructor //******************************************* @@ -74,6 +78,7 @@ namespace etl : data(etl::move(other.data)) { } +#endif //******************************************* // Construct from a value @@ -102,10 +107,12 @@ namespace etl //******************************************* /// Move construct from error //******************************************* +#if ETL_CPP11_SUPPORTED result(TError&& error) : data(etl::move(error)) { } +#endif //******************************************* /// Copy assign @@ -137,11 +144,13 @@ namespace etl //******************************************* /// Move assign from value //******************************************* +#if ETL_CPP11_SUPPORTED result& operator =(TValue&& value) { data = etl::move(value); return *this; } +#endif //******************************************* /// Copy assign from error @@ -155,11 +164,13 @@ namespace etl //******************************************* /// Move assign from error //******************************************* +#if ETL_CPP11_SUPPORTED result& operator =(TError&& error) { data = etl::move(error); return *this; } +#endif //******************************************* /// true if result contains a value @@ -216,10 +227,12 @@ namespace etl /// Returns an rvalue reference to the error. /// Undefined if the result does not contain an error. //******************************************* +#if ETL_CPP11_SUPPORTED TError&& error() { return etl::move(etl::get(data)); } +#endif private: @@ -235,6 +248,9 @@ namespace etl { public: + typedef void value_type; + typedef TError error_type; + //******************************************* /// Default Constructor //******************************************* @@ -269,10 +285,12 @@ namespace etl //******************************************* /// Move construct from error //******************************************* +#if ETL_CPP11_SUPPORTED result(TError&& error) : data(etl::move(error)) { } +#endif //******************************************* /// Copy assign from error @@ -286,11 +304,13 @@ namespace etl //******************************************* /// Move assign from error //******************************************* - result& operator =(TError&& error) +#if ETL_CPP11_SUPPORTED + result& operator =(TError&& err_) { data = etl::move(error); return *this; } +#endif //******************************************* /// true if result contains a value @@ -329,10 +349,12 @@ namespace etl /// Returns an rvalue reference to the error. /// Undefined if the result does not contain an error. //******************************************* +#if ETL_CPP11_SUPPORTED TError&& error() { return etl::move(data.value()); } +#endif private: @@ -446,6 +468,7 @@ namespace etl { return etl::move(data.value()); } +#endif private: @@ -453,5 +476,4 @@ namespace etl }; } -#endif -#endif +#endif \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 58ecbda4..cf1df999 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -102,6 +102,7 @@ add_executable(etl_tests test_error_handler.cpp test_etl_traits.cpp test_exception.cpp + test_expected.cpp test_fixed_iterator.cpp test_fixed_sized_memory_block_allocator.cpp test_flags.cpp diff --git a/test/sanity-check/c++03/CMakeLists.txt b/test/sanity-check/c++03/CMakeLists.txt index 40b4aa96..863f49cd 100644 --- a/test/sanity-check/c++03/CMakeLists.txt +++ b/test/sanity-check/c++03/CMakeLists.txt @@ -129,6 +129,7 @@ target_sources(t98 PRIVATE etl_profile.h ../enum_type.h.t.cpp ../error_handler.h.t.cpp ../exception.h.t.cpp + ../expected.h.t.cpp ../factorial.h.t.cpp ../fibonacci.h.t.cpp ../file_error_numbers.h.t.cpp diff --git a/test/sanity-check/c++11/CMakeLists.txt b/test/sanity-check/c++11/CMakeLists.txt index c08b6f51..65687b9a 100644 --- a/test/sanity-check/c++11/CMakeLists.txt +++ b/test/sanity-check/c++11/CMakeLists.txt @@ -129,6 +129,7 @@ target_sources(t11 PRIVATE etl_profile.h ../enum_type.h.t.cpp ../error_handler.h.t.cpp ../exception.h.t.cpp + ../expected.h.t.cpp ../factorial.h.t.cpp ../fibonacci.h.t.cpp ../file_error_numbers.h.t.cpp diff --git a/test/sanity-check/c++14/CMakeLists.txt b/test/sanity-check/c++14/CMakeLists.txt index f4a7d101..a0462555 100644 --- a/test/sanity-check/c++14/CMakeLists.txt +++ b/test/sanity-check/c++14/CMakeLists.txt @@ -129,6 +129,7 @@ target_sources(t14 PRIVATE etl_profile.h ../enum_type.h.t.cpp ../error_handler.h.t.cpp ../exception.h.t.cpp + ../expected.h.t.cpp ../factorial.h.t.cpp ../fibonacci.h.t.cpp ../file_error_numbers.h.t.cpp diff --git a/test/sanity-check/c++17/CMakeLists.txt b/test/sanity-check/c++17/CMakeLists.txt index 3f3ad303..abaabd55 100644 --- a/test/sanity-check/c++17/CMakeLists.txt +++ b/test/sanity-check/c++17/CMakeLists.txt @@ -129,6 +129,7 @@ target_sources(t17 PRIVATE etl_profile.h ../enum_type.h.t.cpp ../error_handler.h.t.cpp ../exception.h.t.cpp + ../expected.h.t.cpp ../factorial.h.t.cpp ../fibonacci.h.t.cpp ../file_error_numbers.h.t.cpp diff --git a/test/sanity-check/expected.h.t.cpp b/test/sanity-check/expected.h.t.cpp new file mode 100644 index 00000000..2fca92c3 --- /dev/null +++ b/test/sanity-check/expected.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 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. +******************************************************************************/ + +#include diff --git a/test/test_expected.cpp b/test/test_expected.cpp new file mode 100644 index 00000000..3e43e04c --- /dev/null +++ b/test/test_expected.cpp @@ -0,0 +1,447 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2022 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. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/expected.h" +#include "etl/type_traits.h" + +#include +#include + +namespace +{ + struct Value + { + std::string v; + + Value() + { + } + + Value(const std::string v_) + : v(v_) + { + } + + operator std::string() const + { + return v; + } + }; + + struct ValueM + { + ValueM() + { + } + + ValueM(const std::string& v_) + : v(v_) + { + } + + ValueM(ValueM&&) = default; + ValueM& operator =(ValueM&&) = default; + + ValueM(const ValueM&) = delete; + ValueM& operator =(const ValueM&) = delete; + + std::string v; + }; + + struct Error + { + std::string e; + + Error() = default; + Error(const Error&) = default; + Error& operator =(const Error&) = default; + + Error(const std::string e_) + : e(e_) + { + } + + Error& operator =(const std::string e_) + { + e = e_; + } + + operator std::string() const + { + return e; + } + }; + + struct ErrorM + { + ErrorM() + { + } + + ErrorM(const std::string& e_) + : e(e_) + { + } + + ErrorM(ErrorM&&) = default; + ErrorM& operator =(ErrorM&&) = default; + + ErrorM(const ErrorM&) = delete; + ErrorM& operator =(const ErrorM&) = delete; + + std::string e; + }; + + using Expected = etl::expected; + using ExpectedV = etl::expected; + using ExpectedM = etl::expected; + using ExpectedVM = etl::expected; + + using Unexpected = etl::unexpected; + using UnexpectedV = etl::unexpected; + using UnexpectedM = etl::unexpected; +} + +namespace +{ + SUITE(test_result) + { + //************************************************************************* + TEST(test_default_constructor) + { + Expected expected; + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + } + + //************************************************************************* + TEST(test_constructor_for_result_with_value) + { + Value input = { "value 1" }; + Expected expected(input); + + Value output = expected.value(); + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + CHECK_TRUE(output.v == input.v); + } + + //************************************************************************* + TEST(test_constructor_for_const_result_with_value) + { + Value input = { "value 1" }; + const Expected expected(input); + + const Value& output = expected.value(); + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + CHECK_TRUE(output.v == input.v); + } + + //************************************************************************* + TEST(test_constructor_for_moveable_result_with_value) + { + ValueM input = { "value 1" }; + ExpectedM expected(etl::move(input)); + + ValueM output = etl::move(expected.value()); + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + CHECK_TRUE(output.v == std::string("value 1")); + } + + //************************************************************************* + TEST(test_constructor_for_result_with_error) + { + Error input = { "error 1" }; + + Unexpected unexpected(input); + Expected expected(unexpected); + + Error output = expected.error(); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK(output.e == input.e); + } + + //************************************************************************* + TEST(test_constructor_for_const_result_with_error) + { + const Error input = { "error 1" }; + const Unexpected unexpected(input); + const Expected expected(unexpected); + + const Error& output = expected.error(); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK(output.e == input.e); + } + + //************************************************************************* + TEST(test_constructor_for_moveable_result_with_error) + { + ErrorM input = { "error 1" }; + UnexpectedM unexpected(etl::move(input)); + ExpectedM expected(etl::move(unexpected)); + + ErrorM output = etl::move(expected.error()); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK_TRUE(output.e == std::string("error 1")); + } + + //************************************************************************* + TEST(test_constructor_for_result_void_value_with_value) + { + ExpectedV expected; + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + } + + //************************************************************************* + TEST(test_constructor_for_const_result_void_value_with_value) + { + const ExpectedV expected; + + CHECK_TRUE(expected.has_value()); + CHECK_TRUE(bool(expected)); + } + + //************************************************************************* + TEST(test_constructor_for_result_void_value_with_error) + { + Error input = { "error 1" }; + UnexpectedV unexpected(input); + ExpectedV expected(unexpected); + + Error output = expected.error(); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK_TRUE(output.e == input.e); + } + + //************************************************************************* + TEST(test_constructor_for_const_result_void_value_with_error) + { + const Error input = { "error 1" }; + const UnexpectedV unexpected(input); + const ExpectedV expected(unexpected); + + const Error& output = expected.error(); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK_TRUE(output.e == input.e); + } + + //************************************************************************* + TEST(test_constructor_for_moveable_result_void_value_with_error) + { + ErrorM input = { "error 1" }; + UnexpectedM unexpected(etl::move(input)); + ExpectedM expected(etl::move(unexpected)); + + ErrorM output = etl::move(expected.error()); + + CHECK_FALSE(expected.has_value()); + CHECK_FALSE(bool(expected)); + CHECK(output.e == std::string("error 1")); + } + + //************************************************************************* + TEST(test_copy_construct) + { + Value input1 = { "value 1" }; + Expected expected1(input1); + Expected expected2(expected1); + + Value output1 = expected2.value(); + + CHECK_TRUE(expected1.has_value()); + CHECK_TRUE(expected2.has_value()); + CHECK(output1.v == input1.v); + } + + //************************************************************************* + TEST(test_copy_assign) + { + Value input1 = { "value 1" }; + Expected expected1(input1); + + Value input2 = { "value 2" }; + Expected expected2(input2); + + expected2 = expected1; + + Value output1 = expected1.value(); + Value output2 = expected2.value(); + + CHECK_TRUE(expected1.has_value()); + CHECK_TRUE(expected2.has_value()); + + //CHECK(output1.v != input1.v); + //CHECK(output2.v != input1.v); + + //CHECK(output1.v == input2.v); + //CHECK(output2.v == input2.v); + } + + //************************************************************************* + TEST(test_move_construct) + { + ValueM input1 = { "value 1" }; + ExpectedM expected1(etl::move(input1)); + ExpectedM expected2(etl::move(expected1)); + + ValueM output1 = etl::move(expected1.value()); + ValueM output2 = etl::move(expected2.value()); + + CHECK_TRUE(expected1.has_value()); + CHECK_TRUE(expected2.has_value()); + + CHECK_EQUAL("", output1.v); + CHECK_EQUAL("value 1", output2.v); + } + + //************************************************************************* + TEST(test_move_assign) + { + ValueM input1 = { "value 1" }; + ExpectedM expected1(etl::move(input1)); + + ValueM input2 = { "value 2" }; + ExpectedM expected2(etl::move(input2)); + + expected2 = etl::move(expected1); + + ValueM output1 = etl::move(expected1.value()); + ValueM output2 = etl::move(expected2.value()); + + CHECK_TRUE(expected1.has_value()); + CHECK_TRUE(expected2.has_value()); + + CHECK_EQUAL("", output1.v); + CHECK_EQUAL("value 1", output2.v); + } + + //************************************************************************* + TEST(test_copy_construct_void_value) + { + Error input1 = { "error 1" }; + UnexpectedV unexpected1(input1); + ExpectedV expected1(unexpected1); + ExpectedV expected2(expected1); + + CHECK_FALSE(expected1.has_value()); + CHECK_FALSE(expected2.has_value()); + + Error output1 = expected1.error(); + Error output2 = expected2.error(); + + CHECK_EQUAL(input1.e, output1.e); + CHECK_EQUAL(input1.e, output2.e); + } + + //************************************************************************* + TEST(test_copy_assign_void_value) + { + Error input1 = { "error 1" }; + UnexpectedV unexpected1(input1); + + Error input2 = { "error 2" }; + UnexpectedV unexpected2(input2); + + ExpectedV expected1(unexpected1); + ExpectedV expected2(unexpected2); + + expected2 = expected1; + + Error output1 = expected1.error(); + Error output2 = expected2.error(); + + CHECK_FALSE(expected1.has_value()); + CHECK_FALSE(expected2.has_value()); + + CHECK_EQUAL(input1.e, output1.e); + CHECK_EQUAL(input1.e, output2.e); + } + + //************************************************************************* + TEST(test_move_construct_void_value) + { + ErrorM input1 = { "error 1" }; + UnexpectedM unexpected1(etl::move(input1)); + ExpectedVM expected1(etl::move(unexpected1)); + ExpectedVM expected2(etl::move(expected1)); + + ErrorM output1 = etl::move(expected1.error()); + ErrorM output2 = etl::move(expected2.error()); + + CHECK_FALSE(expected1.has_value()); + CHECK_FALSE(expected2.has_value()); + + CHECK_EQUAL("", output1.e); + CHECK_EQUAL("error 1", output2.e); + } + + //************************************************************************* + TEST(test_move_assign_void_value) + { + ErrorM input1 = { "error 1" }; + UnexpectedM unexpected1(etl::move(input1)); + + ErrorM input2 = { "error 2" }; + UnexpectedM unexpected2(etl::move(input2)); + + ExpectedVM expected1(etl::move(unexpected1)); + ExpectedVM expected2(etl::move(unexpected2)); + + expected2 = etl::move(expected1); + + ErrorM output1 = etl::move(expected1.error()); + ErrorM output2 = etl::move(expected2.error()); + + CHECK_FALSE(expected1.has_value()); + CHECK_FALSE(expected2.has_value()); + + CHECK_EQUAL("", output1.e); + CHECK_EQUAL("error 1", output2.e); + } + }; +} diff --git a/test/test_result.cpp b/test/test_result.cpp index 4fbb72bd..e2af3556 100644 --- a/test/test_result.cpp +++ b/test/test_result.cpp @@ -5,7 +5,7 @@ Embedded Template Library. https://github.com/ETLCPP/etl https://www.etlcpp.com -Copyright(c) 2017 John Wellbelove +Copyright(c) 2022 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 @@ -91,55 +91,6 @@ namespace using ResultM = etl::result; } -// Definitions for when the STL and compiler built-ins are not available. -#if ETL_NOT_USING_STL && !defined(ETL_USE_TYPE_TRAITS_BUILTINS) - -using etl::is_copy_constructible; -using etl::is_move_constructible; - -//************************* -template <> -struct etl::is_copy_constructible : public etl::true_type -{ -}; - -template <> -struct etl::is_move_constructible : public etl::true_type -{ -}; - -template <> -struct etl::is_copy_constructible : public etl::true_type -{ -}; - -template <> -struct etl::is_move_constructible : public etl::true_type -{ -}; - -//************************* -template <> -struct etl::is_copy_constructible : public etl::false_type -{ -}; - -template <> -struct etl::is_move_constructible : public etl::false_type -{ -}; - -template <> -struct etl::is_copy_constructible : public etl::false_type -{ -}; - -template <> -struct etl::is_move_constructible : public etl::false_type -{ -}; -#endif - namespace { SUITE(test_result) diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index c855b06b..a88a56dc 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -5630,6 +5630,34 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -11381,6 +11409,7 @@ + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index e6c75e07..693b2073 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -345,9 +345,6 @@ ETL\Utilities - - ETL\Containers - ETL\Containers @@ -1344,6 +1341,12 @@ ETL\Containers + + ETL\Utilities + + + ETL\Utilities + @@ -2192,9 +2195,6 @@ Tests\Maths - - Tests\Containers - Tests\Errors @@ -2231,9 +2231,6 @@ Tests\Misc - - Tests\Misc - Tests\Misc @@ -3392,6 +3389,18 @@ Tests\Sanity Checks\Source + + Tests\Misc + + + Tests\Containers + + + Tests\Containers + + + Tests\Sanity Checks\Source +