Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1969 Add const rvalue 'value' method to 'expected'
Browse files Browse the repository at this point in the history
  • Loading branch information
elBoberido committed May 5, 2023
1 parent ce77591 commit b8ee576
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 20 deletions.
53 changes: 47 additions & 6 deletions iceoryx_hoofs/test/moduletests/test_vocabulary_expected.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,8 @@ TEST_F(expected_test, CreateRValueAndGetErrorResultsInCorrectError)
TEST_F(expected_test, CreateConstRValueAndGetErrorResultsInCorrectError)
{
::testing::Test::RecordProperty("TEST_ID", "936bb9c0-2559-4716-ba03-d5b927fff40f");
constexpr int VALUE_A = 131;
constexpr int VALUE_B = 121;
constexpr int VALUE_A = 123;
constexpr int VALUE_B = 122;
using SutType = expected<int, TestClass>;
auto sut = static_cast<const SutType&&>(SutType(unexpect, VALUE_A, VALUE_B)).error();
EXPECT_THAT(sut.m_a, Eq(VALUE_A));
Expand All @@ -253,8 +253,8 @@ TEST_F(expected_test, CreateConstRValueAndGetErrorResultsInCorrectError)
TEST_F(expected_test, CreateLValueAndGetErrorResultsInCorrectError)
{
::testing::Test::RecordProperty("TEST_ID", "a167d79e-9c50-45d8-afb8-5a4cc2f3da1b");
constexpr int VALUE_A = 131;
constexpr int VALUE_B = 121;
constexpr int VALUE_A = 133;
constexpr int VALUE_B = 112;
auto sut = expected<int, TestClass>(unexpect, VALUE_A, VALUE_B);
EXPECT_THAT(sut.error().m_a, Eq(VALUE_A));
EXPECT_THAT(sut.error().m_b, Eq(VALUE_B));
Expand All @@ -263,13 +263,54 @@ TEST_F(expected_test, CreateLValueAndGetErrorResultsInCorrectError)
TEST_F(expected_test, ConstCreateLValueAndGetErrorResultsInCorrectError)
{
::testing::Test::RecordProperty("TEST_ID", "e56063ea-8b7c-4d47-a898-fe609ea3b283");
constexpr int VALUE_A = 131;
constexpr int VALUE_B = 121;
constexpr int VALUE_A = 112;
constexpr int VALUE_B = 211;
const auto sut = expected<int, TestClass>(unexpect, VALUE_A, VALUE_B);
EXPECT_THAT(sut.error().m_a, Eq(VALUE_A));
EXPECT_THAT(sut.error().m_b, Eq(VALUE_B));
}

TEST_F(expected_test, CreateRValueAndGetValueResultsInCorrectValue)
{
::testing::Test::RecordProperty("TEST_ID", "fb5a3954-50de-419a-b29d-635d068fcb84");
constexpr int VALUE_A = 141;
constexpr int VALUE_B = 131;
auto sut = expected<TestClass, TestError>(in_place, VALUE_A, VALUE_B).value();
EXPECT_THAT(sut.m_a, Eq(VALUE_A));
EXPECT_THAT(sut.m_b, Eq(VALUE_B));
}

TEST_F(expected_test, CreateConstRValueAndGetValueResultsInCorrectValue)
{
::testing::Test::RecordProperty("TEST_ID", "4af92b14-3b70-4ddd-8589-991abe3c8571");
constexpr int VALUE_A = 144;
constexpr int VALUE_B = 113;
using SutType = expected<TestClass, TestError>;
auto sut = static_cast<const SutType&&>(SutType(in_place, VALUE_A, VALUE_B)).value();
EXPECT_THAT(sut.m_a, Eq(VALUE_A));
EXPECT_THAT(sut.m_b, Eq(VALUE_B));
}

TEST_F(expected_test, CreateLValueAndGetValueResultsInCorrectValue)
{
::testing::Test::RecordProperty("TEST_ID", "5adabab2-3329-47bf-bfb7-fe8aa98eacc2");
constexpr int VALUE_A = 114;
constexpr int VALUE_B = 311;
auto sut = expected<TestClass, TestError>(in_place, VALUE_A, VALUE_B);
EXPECT_THAT(sut.value().m_a, Eq(VALUE_A));
EXPECT_THAT(sut.value().m_b, Eq(VALUE_B));
}

TEST_F(expected_test, ConstCreateLValueAndGetValueResultsInCorrectValue)
{
::testing::Test::RecordProperty("TEST_ID", "e33c2d23-7914-4ba7-a8ee-37e3c91c4a74");
constexpr int VALUE_A = 411;
constexpr int VALUE_B = 133;
const auto sut = expected<TestClass, TestError>(in_place, VALUE_A, VALUE_B);
EXPECT_THAT(sut.value().m_a, Eq(VALUE_A));
EXPECT_THAT(sut.value().m_b, Eq(VALUE_B));
}

TEST_F(expected_test, CreateWithValueAndMoveCtorLeadsToMovedSource)
{
::testing::Test::RecordProperty("TEST_ID", "8da72983-3046-4dde-8de5-5eed89de0ccf");
Expand Down
39 changes: 30 additions & 9 deletions iceoryx_hoofs/vocabulary/include/iox/detail/expected.inl
Original file line number Diff line number Diff line change
Expand Up @@ -194,35 +194,56 @@ inline const ErrorType& expected<ValueType, ErrorType>::get_error() const& noexc
return error_checked();
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline const enable_if_non_void_t<U>& expected<ValueType, ErrorType>::value_checked() const& noexcept
{
cxx::ExpectsWithMsg(!has_error(), "Trying to access a value but an error is stored!");
return m_store.value_unchecked();
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline enable_if_non_void_t<U>& expected<ValueType, ErrorType>::value_checked() & noexcept
{
// AXIVION Next Construct AutosarC++19_03-A5.2.3 : const cast to avoid code duplication
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
return const_cast<ValueType&>(const_cast<const expected<ValueType, ErrorType>*>(this)->value_checked());
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline enable_if_non_void_t<U>&& expected<ValueType, ErrorType>::value() && noexcept
{
return std::move(value());
return std::move(value_checked());
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline const enable_if_non_void_t<U>&& expected<ValueType, ErrorType>::value() const&& noexcept
{
return std::move(value_checked());
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline const enable_if_non_void_t<U>& expected<ValueType, ErrorType>::value() const& noexcept
{
cxx::ExpectsWithMsg(!has_error(), "Trying to access a value but an error is stored!");
return m_store.value_unchecked();
return value_checked();
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline enable_if_non_void_t<U>& expected<ValueType, ErrorType>::value() & noexcept
{
// AXIVION Next Construct AutosarC++19_03-A5.2.3 : const cast to avoid code duplication
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
return const_cast<ValueType&>(const_cast<const expected<ValueType, ErrorType>*>(this)->value());
return value_checked();
}

template <typename ValueType, typename ErrorType>
template <typename U>
inline enable_if_non_void_t<U>* expected<ValueType, ErrorType>::operator->() noexcept
{
return &value();
return &value_checked();
}

template <typename ValueType, typename ErrorType>
Expand All @@ -239,7 +260,7 @@ template <typename ValueType, typename ErrorType>
template <typename U>
inline enable_if_non_void_t<U>& expected<ValueType, ErrorType>::operator*() noexcept
{
return value();
return value_checked();
}

template <typename ValueType, typename ErrorType>
Expand Down Expand Up @@ -270,7 +291,7 @@ inline optional<enable_if_non_void_t<U>> expected<ValueType, ErrorType>::to_opti
optional<enable_if_non_void_t<U>> returnValue;
if (!has_error())
{
returnValue.emplace(value());
returnValue.emplace(m_store.value_unchecked());
}
return returnValue;
}
Expand Down
22 changes: 17 additions & 5 deletions iceoryx_hoofs/vocabulary/include/iox/expected.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,29 +253,36 @@ class IOX_NO_DISCARD expected final : public FunctionalInterface<expected<ValueT
/// @deprecated use 'error' instead of 'get_error'
ErrorType&& get_error() && noexcept;

/// @brief returns a reference to the contained success value, if the expected
/// @brief returns a lvalue reference to the contained success value, if the expected
/// does not contain a success value the error handler is called
/// @tparam U helper template parameter for SFINEA
/// @return reference to the internally contained value
/// @return lvalue reference to the internally contained value
/// @note this only works for non void ValueTypes
template <typename U = ValueType>
enable_if_non_void_t<U>& value() & noexcept;

/// @brief returns a const reference to the contained success value, if the expected
/// @brief returns a const lvalue reference to the contained success value, if the expected
/// does not contain a success value the error handler is called
/// @tparam U helper template parameter for SFINEA
/// @return const reference to the internally contained value
/// @return const lvalue reference to the internally contained value
/// @note this only works for non void ValueTypes
template <typename U = ValueType>
const enable_if_non_void_t<U>& value() const& noexcept;

/// @brief returns a reference to the contained success value, if the expected
/// @brief returns a rvalue reference to the contained success value, if the expected
/// does not contain a success value the error handler is called
/// @tparam U helper template parameter for SFINEA
/// @return rvalue reference to the internally contained value
template <typename U = ValueType>
enable_if_non_void_t<U>&& value() && noexcept;

/// @brief returns a const rvalue reference to the contained success value, if the expected
/// does not contain a success value the error handler is called
/// @tparam U helper template parameter for SFINEA
/// @return const rvalue reference to the internally contained value
template <typename U = ValueType>
const enable_if_non_void_t<U>&& value() const&& noexcept;

/// @brief dereferencing operator which returns a reference to the contained
/// success value. if the expected contains an error the error handler is called
/// @tparam U helper template parameter for SFINEA
Expand Down Expand Up @@ -354,6 +361,11 @@ class IOX_NO_DISCARD expected final : public FunctionalInterface<expected<ValueT
friend constexpr bool ::iox::operator==(const expected<T, E>&, const expected<T, E>&) noexcept;

private:
template <typename U = ValueType>
enable_if_non_void_t<U>& value_checked() & noexcept;
template <typename U = ValueType>
const enable_if_non_void_t<U>& value_checked() const& noexcept;

ErrorType& error_checked() & noexcept;
const ErrorType& error_checked() const& noexcept;

Expand Down

0 comments on commit b8ee576

Please sign in to comment.