Skip to content

Commit

Permalink
iox-eclipse-iceoryx#992 Add templated from/into free functions for co…
Browse files Browse the repository at this point in the history
…nversions of enums and other types
  • Loading branch information
elBoberido committed Dec 15, 2021
1 parent f3e3387 commit 5d617d4
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- Axivion analysis on CI[\#409](https://github.com/eclipse-iceoryx/iceoryx/issues/409)
- Cpptoml can be provided by an external source[\#951](https://github.com/eclipse-iceoryx/iceoryx/issues/)
- Extend cxx::optional constructor for in place construction so that copy/move for values inside the optional even could be deleted[\#967](https://github.com/eclipse-iceoryx/iceoryx/issues/967)
- Add templated `from`/`into` free functions to formalize conversions from enums and other types [#992](https://github.com/eclipse-iceoryx/iceoryx/issues/992)

**Bugfixes:**

Expand Down
56 changes: 56 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/convert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
#define IOX_HOOFS_CXX_CONVERT_HPP

#include "iceoryx_hoofs/cxx/string.hpp"
#include "iceoryx_hoofs/cxx/type_traits.hpp"
#include "iceoryx_hoofs/posix_wrapper/posix_call.hpp"

#include <cassert>
#include <climits>
#include <cmath>
#include <cstdlib>
Expand Down Expand Up @@ -91,6 +93,60 @@ class convert
static bool stringIsNumberWithErrorMessage(const char* v, const NumberType type) noexcept;
};

/// @brief Converts a value of type F to a corresponding value of type T. This function needs to be specialized by the
/// user for the types to be converted.
/// @code
/// enum A
/// {
/// A1 = 13,
/// A2
/// };
///
/// enum B
/// {
/// B1 = 42,
/// B2
/// };
///
/// namespace iox
/// {
/// namespace cxx
/// {
/// template <>
/// constexpr B from<A, B>(A e) noexcept
/// {
/// switch (e)
/// {
/// case A1:
/// return B1;
/// case A2:
/// return B2;
/// }
/// }
///
/// } // namespace cxx
/// } // namespace iox
/// @endcode
/// @tparam F is the 'from' type
/// @tparam T is the 'to' type
/// @param[in] value of type F to convert to T
/// @return converted value of F to corresponding value of T
template <typename F, typename T>
constexpr T from(const F value) noexcept;

/// @brief Converts a value of type F to a corresponding value of type T. This is a convenience function which is
/// automatically available when `from` is implemented. This function shall therefore not be specialized but always the
/// `from` function.
/// @code
/// Bar b = iox::cxx::into<Bar>(Foo::ENUM_VALUE);
/// @endcode
/// @tparam T is the 'to' type
/// @tparam F is the 'from' type
/// @param[in] value of type F to convert to T
/// @return converted value of F to corresponding value of T
template <typename T, typename F>
constexpr T into(const F value) noexcept;

} // namespace cxx
} // namespace iox

Expand Down
9 changes: 9 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/type_traits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ struct add_const_conditionally<T, const C>
template <typename T, typename C>
using add_const_conditionally_t = typename add_const_conditionally<T, C>::type;

///
/// @brief Helper value to bind a static_assert to a type
/// @code
/// static_assert(always_false_v<Foo>, "Not implemented for the given type!");
/// @endcode
///
template <typename>
constexpr bool always_false_v = false;

///
/// @brief Verifies whether the passed Callable type is in fact invocable with the given arguments
///
Expand Down
13 changes: 13 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/convert.inl
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,19 @@ inline bool convert::fromString<bool>(const char* v, bool& dest) noexcept
.has_error();
}

template <typename F, typename T>
constexpr T from(const F) noexcept
{
static_assert(always_false_v<F> && always_false_v<T>, "Conversion for the specified types is not implemented!\
Please specialize `template <typename F, typename T> constexpr T from(const F) noexcept`!");
}

template <typename T, typename F>
constexpr T into(const F e) noexcept
{
return from<F, T>(e);
}

} // namespace cxx
} // namespace iox

Expand Down
52 changes: 52 additions & 0 deletions iceoryx_hoofs/test/moduletests/test_cxx_convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,41 @@


#include <cstdint>

namespace
{
enum A
{
A1 = 13,
A2
};

enum B
{
B1 = 42,
B2
};
} // namespace

namespace iox
{
namespace cxx
{
template <>
constexpr B from<A, B>(A e) noexcept
{
switch (e)
{
case A1:
return B1;
case A2:
return B2;
}
}

} // namespace cxx
} // namespace iox

namespace
{
using namespace ::testing;
Expand Down Expand Up @@ -365,4 +400,21 @@ TEST_F(convert_test, fromString_MinMaxUNSIGNED_Int)
source = "-1";
EXPECT_THAT(iox::cxx::convert::fromString(source.c_str(), destination), Eq(false));
}

TEST(convert_free_functions_test, fromWorksAsConstexpr)
{
constexpr A FROM_VALUE{A1};
constexpr B TO_VALUE{B1};
constexpr B SUT = iox::cxx::from<A, B>(FROM_VALUE);
EXPECT_EQ(SUT, TO_VALUE);
}

TEST(convert_free_functions_test, intoWorksWhenFromIsSpecialized)
{
constexpr A FROM_VALUE{A2};
constexpr B TO_VALUE{B2};
constexpr B SUT = iox::cxx::into<B>(FROM_VALUE);
EXPECT_EQ(SUT, TO_VALUE);
}

} // namespace
8 changes: 8 additions & 0 deletions iceoryx_hoofs/test/moduletests/test_cxx_type_traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,14 @@ TEST(TypeTraitsTest, AddConstConditionallyTypeAliasWorks)
EXPECT_TRUE(std::is_const<SutTypeResult>::value);
}

TEST(TypeTraitsTest, AlwaysFalseWorks)
{
struct Foo
{
};
EXPECT_FALSE(always_false_v<Foo>);
}

TEST(TypeTraitsTest, IsFunctionPointerResolvesToTrue)
{
auto result = is_function_pointer<void (*)(double)>::value;
Expand Down

0 comments on commit 5d617d4

Please sign in to comment.