Skip to content

Commit

Permalink
iox-eclipse-iceoryx#1751 Add equality operators for 'cxx::variant'
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Hoinkis <[email protected]>
  • Loading branch information
mossmaurice committed Oct 20, 2022
1 parent 429348a commit aa337f0
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 3 deletions.
27 changes: 26 additions & 1 deletion iceoryx_hoofs/include/iceoryx_hoofs/cxx/variant.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -158,12 +158,16 @@ class variant
/// @brief if the variant contains an element the elements move constructor is called
/// otherwise an empty variant is moved
/// @param[in] rhs source of the move
/// @note The move c'tor does not explicitly invalidate the moved-from object but relies on the move c'tor of
/// Types to correctly invalidate the stored object
constexpr variant(variant&& rhs) noexcept;

/// @brief if the variant contains an element the elements move assignment operator is called
/// otherwise an empty variant is moved
/// @param[in] rhs source of the move assignment
/// @return reference to the variant itself
/// @note The move assign operator does not explicitly invalidate the moved-from object but relies on the move
/// assign operator of Types to correctly invalidate the stored object
constexpr variant& operator=(variant&& rhs) noexcept;

/// @brief if the variant contains an element the elements destructor is called otherwise
Expand Down Expand Up @@ -273,12 +277,33 @@ class variant
static void error_message(const char* source, const char* msg) noexcept;

void call_element_destructor() noexcept;

template <typename... Ts>
friend constexpr bool operator==(const variant<Ts...>& lhs, const variant<Ts...>& rhs);
template <typename... Ts>
friend constexpr bool operator!=(const variant<Ts...>& lhs, const variant<Ts...>& rhs);
};

/// @brief returns true if the variant holds a given type T, otherwise false
template <typename T, typename... Types>
constexpr bool holds_alternative(const variant<Types...>& variant) noexcept;

/// @brief equality check for two distinct variant types
/// @tparam Types variadic number of types which can be stored in the variant
/// @param[in] lhs left side of the comparision
/// @param[in] rhs right side of the comparision
/// @return true if the variants are equal, otherwise false
template <typename... Types>
constexpr bool operator==(const variant<Types...>& lhs, const variant<Types...>& rhs);

/// @brief inequality check for two distinct variant types
/// @tparam Types variadic number of types which can be stored in the variant
/// @param[in] lhs left side of the comparision
/// @param[in] rhs right side of the comparision
/// @return true if the variants are not equal, otherwise false
template <typename... Types>
constexpr bool operator!=(const variant<Types...>& lhs, const variant<Types...>& rhs);

} // namespace cxx
} // namespace iox

Expand Down
25 changes: 23 additions & 2 deletions iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/variant.inl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2019 by Robert Bosch GmbH. All rights reserved.
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 by Perforce All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -19,6 +19,7 @@
#define IOX_HOOFS_CXX_VARIANT_INL

#include "iceoryx_hoofs/cxx/variant.hpp"
#include "iceoryx_hoofs/log/logging.hpp"

namespace iox
{
Expand Down Expand Up @@ -288,14 +289,34 @@ inline bool variant<Types...>::has_bad_variant_element_access() const noexcept
template <typename... Types>
inline void variant<Types...>::error_message(const char* source, const char* msg) noexcept
{
std::cerr << source << " ::: " << msg << std::endl;
IOX_LOG(ERROR) << source << " ::: " << msg;
}

template <typename T, typename... Types>
inline constexpr bool holds_alternative(const variant<Types...>& variant) noexcept
{
return variant.template get<T>() != nullptr;
}

template <typename... Types>
constexpr bool operator==(const variant<Types...>& lhs, const variant<Types...>& rhs)
{
if ((lhs.index() == INVALID_VARIANT_INDEX) && (rhs.index() == INVALID_VARIANT_INDEX))
{
return true;
}
if (lhs.index() != rhs.index())
{
return false;
}
return internal::call_at_index<0, Types...>::equality(lhs.index(), lhs.m_storage, rhs.m_storage);
}

template <typename... Types>
constexpr bool operator!=(const variant<Types...>& lhs, const variant<Types...>& rhs)
{
return !(lhs == rhs);
}
} // namespace cxx
} // namespace iox

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,17 @@ struct call_at_index
call_at_index<N + 1, Targs...>::copyConstructor(index, source, destination);
}
}

static bool equality(const uint64_t index, const byte_t* lhs, const byte_t* rhs)
{
if (N == index)
{
// AXIVION Next Construct AutosarC++19_03-A5.2.4 : Type safety ensured through template parameter and encapsulated in this class
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return *reinterpret_cast<const T*>(lhs) == *reinterpret_cast<const T*>(rhs);
}
return call_at_index<N + 1, Targs...>::equality(index, lhs, rhs);
}
};

template <uint64_t N, typename T>
Expand Down Expand Up @@ -245,6 +256,20 @@ struct call_at_index<N, T>
assert(false && "Could not call copy constructor for variant element");
}
}

// NOLINTJUSTIFICATION 'operator new()' needs non-const 'destination'
// NOLINTNEXTLINE(readability-non-const-parameter)
static bool equality(const uint64_t index, const byte_t* lhs, const byte_t* rhs) noexcept
{
if (N == index)
{
// AXIVION Next Construct AutosarC++19_03-A5.2.4 : Type safety ensured through template parameter and encapsulated in this class
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
return *reinterpret_cast<const T*>(lhs) == *reinterpret_cast<const T*>(rhs);
}
assert(false && "Could not call equality operator for variant element");
return false;
}
};

} // namespace internal
Expand Down
38 changes: 38 additions & 0 deletions iceoryx_hoofs/test/moduletests/test_cxx_variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "iceoryx_hoofs/cxx/variant.hpp"
#include "test.hpp"
#include <variant>

#include <string>
namespace
Expand Down Expand Up @@ -703,4 +704,41 @@ TEST_F(variant_Test, CopyVariantIntoVariantOfDifferentType)

EXPECT_THAT(DoubleDelete::dtorCalls, Eq(1));
}

TEST_F(variant_Test, TwoInvalidVariantsAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "4b2b7516-48ef-4aa6-a0c5-43a204e1e348");
iox::cxx::variant<std::string, float> sut1;
iox::cxx::variant<std::string, float> sut2;
EXPECT_TRUE(sut1 == sut2);
}

TEST_F(variant_Test, InvalidAndValidVariantAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "0c77c24f-059b-4298-b4a2-0a7d8eb70364");
std::string string{"Foo"};
iox::cxx::variant<std::string, float> sut1{string};
iox::cxx::variant<std::string, float> sut2;
EXPECT_FALSE(sut1 == sut2);
}

TEST_F(variant_Test, TwoVariantsWithEqualValuesAreEqual)
{
::testing::Test::RecordProperty("TEST_ID", "6496566e-647d-426b-b369-7ec27c6ee673");
std::string string{"Foo"};
iox::cxx::variant<std::string, float> sut1{string};
iox::cxx::variant<std::string, float> sut2{string};
EXPECT_TRUE(sut1 == sut2);
}

TEST_F(variant_Test, TwoVariantsWithUnequalValueAreUnequal)
{
::testing::Test::RecordProperty("TEST_ID", "b37c2f64-6ba6-42c8-9b6d-73bb344b8c8e");
std::string string{"Foo"};
float floatNum{42.42F};
iox::cxx::variant<std::string, float> sut1{string};
iox::cxx::variant<std::string, float> sut2{floatNum};
EXPECT_FALSE(sut1 == sut2);
}

} // namespace

0 comments on commit aa337f0

Please sign in to comment.