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 76ba504 commit 91db512
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 1 deletion.
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
60 changes: 59 additions & 1 deletion iceoryx_hoofs/include/iceoryx_hoofs/cxx/helplets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
#ifndef IOX_HOOFS_CXX_HELPLETS_HPP
#define IOX_HOOFS_CXX_HELPLETS_HPP

#include <assert.h>
#include "iceoryx_hoofs/cxx/type_traits.hpp"

#include <cassert>
#include <cstdint>
#include <cstring>
#include <iostream>
Expand Down Expand Up @@ -277,6 +279,62 @@ bool isValidFileName(const string<StringCapacity>& name) noexcept;
template <uint64_t StringCapacity>
bool isValidFilePath(const string<StringCapacity>& name) 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 class LowLevel
/// {
/// FileDescriptorInvalid,
/// FileDescriptorCorrupt,
/// Timeout
/// };
///
/// enum class HighLevel
/// {
/// FileDescriptorError,
/// Timeout
/// };
///
/// namespace iox
/// {
/// namespace cxx
/// {
/// template <>
/// constexpr HighLevel from<LowLevel, HighLevel>(LowLevel e) noexcept
/// {
/// switch (e)
/// {
/// case LowLevel::FileDescriptorCorrupt:
/// return HighLevel::FileDescriptorError;
/// case LowLevel::FileDescriptorInvalid:
/// return HighLevel::FileDescriptorError;
/// case LowLevel::Timeout:
/// return HighLevel::Timeout;
/// }
/// }
/// } // 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/helplets.inl
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,19 @@ inline bool isValidFilePath(const string<StringCapacity>& name) noexcept

return false;
}

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
49 changes: 49 additions & 0 deletions iceoryx_hoofs/test/moduletests/test_cxx_helplets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,40 @@
#include <string>
#include <type_traits>

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 @@ -449,5 +483,20 @@ TEST(Helplets_test_isValidFilePath, EmptyFilePathIsInvalid)
EXPECT_FALSE(isValidFilePath(string<FILE_PATH_LENGTH>("")));
}

TEST(Helplets_test_from, 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(Helplets_test_into, 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 91db512

Please sign in to comment.