Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1751 Add equality operators for 'cxx::expected'
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Hoinkis <[email protected]>
  • Loading branch information
mossmaurice committed Oct 26, 2022
1 parent 3aecfb8 commit e3fb150
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
34 changes: 34 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/expected.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,40 @@ class IOX_NO_DISCARD expected<void, ErrorType> : public expected<ErrorType>
using expected<ErrorType>::expected;
};

/// @brief equality check for two distinct expected types
/// @tparam ErrorType type of the error stored in the expected
/// @param[in] lhs left side of the comparison
/// @param[in] rhs right side of the comparison
/// @return true if the expecteds are equal, otherwise false
template <typename ErrorType>
constexpr bool operator==(const expected<ErrorType>& lhs, const expected<ErrorType>& rhs);

/// @brief inequality check for two distinct expected types
/// @tparam ErrorType type of the error stored in the expected
/// @param[in] lhs left side of the comparison
/// @param[in] rhs right side of the comparison
/// @return true if the expecteds are not equal, otherwise false
template <typename ErrorType>
constexpr bool operator!=(const expected<ErrorType>& lhs, const expected<ErrorType>& rhs);

/// @brief equality check for two distinct expected types
/// @tparam ValueType type of the value stored in the expected
/// @tparam ErrorType type of the error stored in the expected
/// @param[in] lhs left side of the comparison
/// @param[in] rhs right side of the comparison
/// @return true if the expecteds are equal, otherwise false
template <typename ValueType, typename ErrorType>
constexpr bool operator==(const expected<ValueType, ErrorType>& lhs, const expected<ValueType, ErrorType>& rhs);

/// @brief inequality check for two distinct expected types
/// @tparam ValueType type of the value stored in the expected
/// @tparam ErrorType type of the error stored in the expected
/// @param[in] lhs left side of the comparison
/// @param[in] rhs right side of the comparison
/// @return true if the expecteds are not equal, otherwise false
template <typename ValueType, typename ErrorType>
constexpr bool operator!=(const expected<ValueType, ErrorType>& lhs, const expected<ValueType, ErrorType>& rhs);

} // namespace cxx
} // namespace iox

Expand Down
41 changes: 41 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/expected.inl
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,47 @@ inline const ErrorType& expected<ErrorType>::get_error_unchecked() const noexcep
{
return *m_store.template get_at_index<ERROR_INDEX>();
}

template <typename ErrorType>
inline constexpr bool operator==(const expected<ErrorType>& lhs, const expected<ErrorType>& rhs)
{
if (lhs.has_error() != rhs.has_error())
{
return false;
}
if (lhs.has_error() && rhs.has_error())
{
return lhs.get_error() == rhs.get_error();
}
return true;
}

template <typename ErrorType>
inline constexpr bool operator!=(const expected<ErrorType>& lhs, const expected<ErrorType>& rhs)
{
return !(lhs == rhs);
}

template <typename ValueType, typename ErrorType>
inline constexpr bool operator==(const expected<ValueType, ErrorType>& lhs, const expected<ValueType, ErrorType>& rhs)
{
if (lhs.has_error() != rhs.has_error())
{
return false;
}
if (lhs.has_error() && rhs.has_error())
{
return lhs.get_error() == rhs.get_error();
}
return lhs.value() == rhs.value();
}

template <typename ValueType, typename ErrorType>
inline constexpr bool operator!=(const expected<ValueType, ErrorType>& lhs, const expected<ValueType, ErrorType>& rhs)
{
return !(lhs == rhs);
}

} // namespace cxx
} // namespace iox

Expand Down
95 changes: 95 additions & 0 deletions iceoryx_hoofs/test/moduletests/test_cxx_expected.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -699,4 +699,99 @@ TEST_F(expected_test, AccessingErrorOfRValueExpectedWhichContainsValueLeadsToErr
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, cppcoreguidelines-avoid-goto, hicpp-avoid-goto, hicpp-vararg)
EXPECT_DEATH({ std::move(sut).get_error(); }, "Trying to access an error but a value is stored");
}

TEST_F(expected_test, TwoErrorOnlyExpectedWithEqualErrorAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "471b406d-8dd3-4b82-9d46-00c21d257461");
auto sut1 = expected<TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestError>::create_error(TestError::ERROR1);

EXPECT_TRUE(sut1 == sut2);
EXPECT_FALSE(sut1 != sut2);
}

TEST_F(expected_test, TwoErrorOnlyExpectedWithUnequalErrorAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "bcc2f9f1-72a1-41ed-ac8a-2f48cdcfbc56");
auto sut1 = expected<TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestError>::create_error(TestError::ERROR2);

EXPECT_FALSE(sut1 == sut2);
EXPECT_TRUE(sut1 != sut2);
}

TEST_F(expected_test, TwoErrorOnlyExpectedWithValuesAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "75b25c16-fb79-4589-ab0f-bc73bb9fc2bb");
auto sut1 = expected<TestError>::create_value();
auto sut2 = expected<TestError>::create_value();

EXPECT_TRUE(sut1 == sut2);
EXPECT_FALSE(sut1 != sut2);
}

TEST_F(expected_test, TwoErrorOnlyExpectedWithErrorAndValueAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "2108715f-e71c-4778-bb64-553996e860b4");
auto sut1 = expected<TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestError>::create_value();

EXPECT_FALSE(sut1 == sut2);
EXPECT_TRUE(sut1 != sut2);
}

TEST_F(expected_test, TwoExpectedWithEqualErrorAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "b1a3b106-06f2-4667-ac25-7a9d9689c219");
auto sut1 = expected<TestClass, TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestClass, TestError>::create_error(TestError::ERROR1);

EXPECT_TRUE(sut1 == sut2);
EXPECT_FALSE(sut1 != sut2);
}

TEST_F(expected_test, TwoExpectedsWithUnequalErrorAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "25250c6b-aa8f-40ad-ace9-2c55ce8eeaa2");
auto sut1 = expected<TestClass, TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestClass, TestError>::create_error(TestError::ERROR2);

EXPECT_FALSE(sut1 == sut2);
EXPECT_TRUE(sut1 != sut2);
}

TEST_F(expected_test, TwoExpectedWithEqualValueAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "278c2fd5-2b48-49d1-a8a4-8ca52b99de41");
constexpr int VAL_1{42};
constexpr int VAL_2{73};
auto sut1 = expected<TestClass, TestError>::create_value(VAL_1, VAL_2);
auto sut2 = expected<TestClass, TestError>::create_value(VAL_1, VAL_2);

EXPECT_TRUE(sut1 == sut2);
EXPECT_FALSE(sut1 != sut2);
}

TEST_F(expected_test, TwoExpectedWithUnequalValueAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "5f6a8760-6fdf-4ab8-a7d5-d751390aa672");
constexpr int VAL_1{42};
constexpr int VAL_2{73};
auto sut1 = expected<TestClass, TestError>::create_value(VAL_1, VAL_1);
auto sut2 = expected<TestClass, TestError>::create_value(VAL_2, VAL_2);

EXPECT_FALSE(sut1 == sut2);
EXPECT_TRUE(sut1 != sut2);
}

TEST_F(expected_test, TwoExpectedWithErrorAndValueAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "aa912753-09af-46d5-92d5-52cad69795ad");
constexpr int VAL{42};
auto sut1 = expected<TestClass, TestError>::create_error(TestError::ERROR1);
auto sut2 = expected<TestClass, TestError>::create_value(VAL, VAL);

EXPECT_FALSE(sut1 == sut2);
EXPECT_TRUE(sut1 != sut2);
}
} // namespace

0 comments on commit e3fb150

Please sign in to comment.