Merge branch 'feature/#615-addition-of-etl--expected' into development

This commit is contained in:
John Wellbelove 2023-02-08 20:34:21 +01:00
commit 4fce31b742
16 changed files with 1208 additions and 117 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -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 <typename TError>
class expected_invalid;
//*******************************************
template<>
class expected_invalid<void> : 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 <typename TError>
class expected_invalid : etl::expected_invalid<void>
{
public:
expected_invalid(string_type file_name_, numeric_type line_number_)
: expected_invalid<void>(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 <typename TErr = TError, typename = typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::unexpected<TErr>>::value &&
template <typename TErr = TError, typename = typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, unexpected>::value &&
!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::in_place_t>::value, int>::type>
constexpr explicit unexpected(TErr&& e)
: error_value(etl::forward<TErr>(e))
{
}
#else
//*******************************************
/// Construct from argument.
//*******************************************
template <typename TErr>
explicit unexpected(const TErr& e, typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::unexpected<TErr> >::value &&
!etl::is_same<typename etl::remove_cvref<TErr>::type, etl::in_place_t>::value, int>::type = 0)
explicit unexpected(const TErr& e, typename = typename etl::enable_if<!etl::is_same<typename etl::remove_cvref<TErr>::type, unexpected>::value &&
!etl::is_same<typename etl::remove_cvref<TErr>::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<TError>& operator =(const etl::unexpected<TError>& rhs)
etl::unexpected<TError>& operator =(const etl::unexpected<TError>& rhs)
{
error_value = rhs.error_value;
ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::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<TError>& operator =(etl::unexpected<TError>&& rhs)
etl::unexpected<TError>& operator =(etl::unexpected<TError>&& rhs)
{
error_value = etl::move(rhs.error_value);
ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::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 <typename TError>
unexpected(TError) -> unexpected<TError>;
inline constexpr unexpect_t unexpect{};
#else
static const unexpect_t unexpect;
#endif
//*****************************************************************************
/// Expected type.
//*****************************************************************************
template <typename TValue, typename TError>
class expected
{
public:
typedef etl::expected<TValue, TError> this_type;
typedef TValue value_type;
typedef TError error_type;
typedef etl::unexpected<TError> unexpected_type;
template <typename U>
using rebind = expected<U, TError>;
//*******************************************
/// Default constructor
//*******************************************
ETL_CONSTEXPR14 expected() ETL_NOEXCEPT
: storage(etl::in_place_index<Value_Type>, value_type())
{
}
//*******************************************
/// Constructor
//*******************************************
ETL_CONSTEXPR14 expected(const value_type& value_) ETL_NOEXCEPT
: storage(etl::in_place_index<Value_Type>, value_)
{
}
//*******************************************
/// Constructor
//*******************************************
ETL_CONSTEXPR14 expected(value_type&& value_) ETL_NOEXCEPT
: storage(etl::in_place_index<Value_Type>, 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 <typename F>
ETL_CONSTEXPR14 explicit expected(const etl::unexpected<F>& ue)
: storage(etl::in_place_index<Error_Type>, ue.error())
{
}
//*******************************************
/// Move construct from unexpected type.
//*******************************************
template <typename F>
ETL_CONSTEXPR14 explicit expected(etl::unexpected<F>&& ue)
: storage(etl::in_place_index<Error_Type>, 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 <typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::in_place_t, Args&&... args)
: storage(etl::forward<Args>(args)...)
{
}
//*******************************************
/// Construct value type from initializser_list and arguments.
//*******************************************
template <typename U, typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::in_place_t, std::initializer_list<U> il, Args&&... args)
: storage(il, etl::forward<Args>(args)...)
{
}
//*******************************************
/// Construct error type from arguments.
//*******************************************
template <typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, Args&&... args)
: storage(error_type(etl::forward<Args>(args)...))
{
}
//*******************************************
/// Construct error type from initializser_list and arguments.
//*******************************************
template <typename U, typename... Args>
ETL_CONSTEXPR14 explicit expected(etl::unexpect_t, std::initializer_list<U> il, Args&&... args)
: storage(error_type(il, etl::forward<Args>(args)...))
{
}
//*******************************************
///
//*******************************************
this_type& operator =(const this_type& other)
{
ETL_STATIC_ASSERT(etl::is_copy_constructible<TValue>::value && etl::is_copy_constructible<TError>::value, "Not copy assignable");
storage = other.storage;
return *this;
}
//*******************************************
///
//*******************************************
this_type& operator =(this_type&& other)
{
ETL_STATIC_ASSERT(etl::is_move_constructible<TValue>::value && etl::is_move_constructible<TError>::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<TValue>::value, "Value not copy assignable");
storage.emplace<Value_Type>(value);
return *this;
}
//*******************************************
/// Move assign from value
//*******************************************
expected& operator =(value_type&& value)
{
ETL_STATIC_ASSERT(etl::is_move_constructible<TValue>::value, "Value not move assignable");
storage.emplace<Value_Type>(etl::move(value));
return *this;
}
//*******************************************
/// Copy assign from error
//*******************************************
expected& operator =(const unexpected_type& error)
{
ETL_STATIC_ASSERT(etl::is_copy_constructible<TError>::value, "Error not copy assignable");
storage.emplace<Error_Type>(error);
return *this;
}
//*******************************************
/// Move assign from error
//*******************************************
expected& operator =(unexpected_type&& error)
{
ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Error not move assignable");
storage.emplace<Error_Type>(etl::move(error));
return *this;
}
//*******************************************
///
//*******************************************
ETL_CONSTEXPR14 value_type& value()&
{
return etl::get<Value_Type>(storage);
}
//*******************************************
///
//*******************************************
ETL_CONSTEXPR14 const value_type& value() const&
{
return etl::get<Value_Type>(storage);
}
//*******************************************
///
//*******************************************
ETL_CONSTEXPR14 value_type&& value()&&
{
return etl::move(etl::get<Value_Type>(storage));
}
//*******************************************
///
//*******************************************
ETL_CONSTEXPR14 const value_type&& value() const&&
{
return etl::move(etl::get<Value_Type>(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 <typename U>
ETL_NODISCARD
ETL_CONSTEXPR14
value_type value_or(U&& default_value) const&
{
if (has_value())
{
return value();
}
else
{
return default_value;
}
}
//*******************************************
///
//*******************************************
template <typename U>
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<Error_Type>(storage);
}
//*******************************************
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
const error_type& error() const& ETL_NOEXCEPT
{
return etl::get<Error_Type>(storage);
}
//*******************************************
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
error_type&& error() && ETL_NOEXCEPT
{
return etl::move(etl::get<Error_Type>(storage));
}
//*******************************************
///
//*******************************************
ETL_NODISCARD
ETL_CONSTEXPR14
const error_type&& error() const&& ETL_NOEXCEPT
{
return etl::move(etl::get<Error_Type>(storage));
}
//*******************************************
///
//*******************************************
template <typename... Args>
ETL_CONSTEXPR14 value_type& emplace(Args&&... args) ETL_NOEXCEPT
{
storage.emplace(args...);
}
//*******************************************
///
//*******************************************
template <typename U, typename... Args>
ETL_CONSTEXPR14 value_type& emplace(std::initializer_list<U>& 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<Value_Type>());
}
//*******************************************
///
//*******************************************
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>());
}
//*******************************************
///
//*******************************************
value_type& operator *()
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(expected_invalid));
#endif
return storage.get<Value_Type>();
}
//*******************************************
///
//*******************************************
const value_type& operator *() const
{
#if ETL_IS_DEBUG_BUILD
ETL_ASSERT(valid, ETL_ERROR(expected_invalid));
#endif
return storage.get<Value_Type>();
}
private:
enum
{
Uninitialised,
Value_Type,
Error_Type
};
using storage_type = etl::variant<etl::monostate, value_type, error_type>;
storage_type storage;
};
//*****************************************************************************
/// Specialisation for void value type.
//*****************************************************************************
template<typename TError>
class expected<void, TError>
{
public:
typedef etl::expected<void, TError> this_type;
typedef void value_type;
typedef TError error_type;
typedef etl::unexpected<TError> 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<TError>::value, "Not copy assignable");
storage = other.storage;
return *this;
}
//*******************************************
/// Move assign
//*******************************************
this_type& operator =(this_type&& other)
{
ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::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<TError>::value, "Error not copy assignable");
storage.emplace<Error_Type>(error);
return *this;
}
//*******************************************
/// Move assign from error
//*******************************************
expected& operator =(unexpected_type&& error)
{
ETL_STATIC_ASSERT(etl::is_move_constructible<TError>::value, "Error not move assignable");
storage.emplace<Error_Type>(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<Error_Type>(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<Error_Type>(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<Error_Type>(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<Error_Type>(storage));
}
private:
enum
{
Uninitialised,
Error_Type
};
etl::variant<etl::monostate, error_type> storage;
};
}
//*******************************************
@ -234,20 +846,5 @@ void swap(etl::unexpected<TError>& lhs, etl::unexpected<TError>& 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

View File

@ -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

View File

@ -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 <typename T, bool is_pod = etl::is_pod<T>::value>
@ -521,6 +521,8 @@ namespace etl
//*****************************************************************************
/// For POD types.
///\tparam T The type to store.
///\ingroup utilities
//*****************************************************************************
template <typename T>
class optional<T, true>

View File

@ -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;

View File

@ -50,10 +50,13 @@ namespace etl
/// Result type.
//*****************************************************************************
template <typename TValue, typename TError>
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
//*******************************************
/// <b>true</b> 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<TError>(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
//*******************************************
/// <b>true</b> 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 <etl/expected.h>

447
test/test_expected.cpp Normal file
View File

@ -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 <string>
#include <variant>
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<Value, Error>;
using ExpectedV = etl::expected<void, Error>;
using ExpectedM = etl::expected<ValueM, ErrorM>;
using ExpectedVM = etl::expected<void, ErrorM>;
using Unexpected = etl::unexpected<Error>;
using UnexpectedV = etl::unexpected<Error>;
using UnexpectedM = etl::unexpected<ErrorM>;
}
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);
}
};
}

View File

@ -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<ValueM, ErrorM>;
}
// 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<Value> : public etl::true_type
{
};
template <>
struct etl::is_move_constructible<Value> : public etl::true_type
{
};
template <>
struct etl::is_copy_constructible<Error> : public etl::true_type
{
};
template <>
struct etl::is_move_constructible<Error> : public etl::true_type
{
};
//*************************
template <>
struct etl::is_copy_constructible<ValueM> : public etl::false_type
{
};
template <>
struct etl::is_move_constructible<ValueM> : public etl::false_type
{
};
template <>
struct etl::is_copy_constructible<ErrorM> : public etl::false_type
{
};
template <>
struct etl::is_move_constructible<ErrorM> : public etl::false_type
{
};
#endif
namespace
{
SUITE(test_result)

View File

@ -5630,6 +5630,34 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='MSVC Debug - Appveyor|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug64|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\sanity-check\expected.h.t.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - Small Strings|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='MSVC Debug - Appveyor|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='MSVC Debug - No STL - Appveyor|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No STL - Force Constexpr Algorithms|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug LLVM C++20|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - No Unit Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug LLVM|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No STL - Built-ins|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug LLVM - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No STL - Force Built-ins|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug LLVM - No STL - Built-ins|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug64|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - String Truncation Is Error|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Clang|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - No STL - Force No Advanced|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - Force cpp03|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Intel - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Intel|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - No Checks|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - Force C++03|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\sanity-check\message_broker.h.t.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC - Small Strings|Win32'">true</ExcludedFromBuild>
@ -11381,6 +11409,7 @@
<ClCompile Include="..\test_crc8_maxim.cpp" />
<ClCompile Include="..\test_crc8_rohc.cpp" />
<ClCompile Include="..\test_crc8_wcdma.cpp" />
<ClCompile Include="..\test_expected.cpp" />
<ClCompile Include="..\test_message_broker.cpp" />
<ClCompile Include="..\test_poly_span_dynamic_extent.cpp" />
<ClCompile Include="..\test_poly_span_fixed_extent.cpp" />

View File

@ -345,9 +345,6 @@
<ClInclude Include="..\..\include\etl\io_port.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\optional.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\set.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
@ -1344,6 +1341,12 @@
<ClInclude Include="..\..\include\etl\expected.h">
<Filter>ETL\Containers</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\optional.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
<ClInclude Include="..\..\include\etl\optional.h">
<Filter>ETL\Utilities</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\test_string_char.cpp">
@ -2192,9 +2195,6 @@
<ClCompile Include="..\test_random.cpp">
<Filter>Tests\Maths</Filter>
</ClCompile>
<ClCompile Include="..\test_optional.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
<ClCompile Include="..\test_error_handler.cpp">
<Filter>Tests\Errors</Filter>
</ClCompile>
@ -2231,9 +2231,6 @@
<ClCompile Include="..\test_parameter_type.cpp">
<Filter>Tests\Misc</Filter>
</ClCompile>
<ClCompile Include="..\test_result.cpp">
<Filter>Tests\Misc</Filter>
</ClCompile>
<ClCompile Include="..\test_utility.cpp">
<Filter>Tests\Misc</Filter>
</ClCompile>
@ -3392,6 +3389,18 @@
<ClCompile Include="..\sanity-check\to_arithmetic.h.t.cpp">
<Filter>Tests\Sanity Checks\Source</Filter>
</ClCompile>
<ClCompile Include="..\test_optional.cpp">
<Filter>Tests\Misc</Filter>
</ClCompile>
<ClCompile Include="..\test_result.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
<ClCompile Include="..\test_expected.cpp">
<Filter>Tests\Containers</Filter>
</ClCompile>
<ClCompile Include="..\sanity-check\expected.h.t.cpp">
<Filter>Tests\Sanity Checks\Source</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="..\..\library.properties">