Skip to content

Commit

Permalink
Support etl::underlying_type with compiler builtin
Browse files Browse the repository at this point in the history
msvc is unsupported currently
  • Loading branch information
Chiang, Yi committed Mar 10, 2025
1 parent 37539a2 commit 555d710
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 1 deletion.
35 changes: 35 additions & 0 deletions include/etl/generators/type_traits_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -2302,6 +2302,41 @@ typedef integral_constant<bool, true> true_type;
using type_identity_t = typename type_identity<T>::type;
#endif

#if ETL_USING_BUILTIN_UNDERLYING_TYPE
namespace private_type_traits
{
template <typename T, bool = is_enum<T>::value>
struct __underlying_type_impl;

template <typename T>
struct __underlying_type_impl<T, false>
{
};

template <typename T>
struct __underlying_type_impl<T, true>
{
using type = __underlying_type(T);
};
}

template <typename T>
struct underlying_type : private_type_traits::__underlying_type_impl<T, is_enum<T>::value>
{
};

#if ETL_USING_CPP11
template <typename T>
using underlying_type_t = typename underlying_type<T>::type;

template <typename T>
ETL_CONSTEXPR underlying_type_t<T> to_underlying(T val) ETL_NOEXCEPT
{
return static_cast<underlying_type_t<T>>(val);
}
#endif
#endif

#if ETL_USING_CPP11
//*********************************************
// has_duplicates
Expand Down
12 changes: 12 additions & 0 deletions include/etl/profiles/determine_builtin_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ SOFTWARE.
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 1
#endif

#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 1
#endif
#endif

#if defined(__has_builtin) // Use __has_builtin to check for existence of builtin functions?
Expand All @@ -73,6 +77,10 @@ SOFTWARE.
#if !defined(ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE)
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE (__has_builtin(__has_trivial_copy) || __has_builtin(__is_trivially_copyable))
#endif

#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE __has_builtin(__underlying_type)
#endif
#endif

// The default. Set to 0, if not already set.
Expand All @@ -96,6 +104,10 @@ SOFTWARE.
#define ETL_USING_BUILTIN_IS_TRIVIALLY_COPYABLE 0
#endif

#if !defined(ETL_USING_BUILTIN_UNDERLYING_TYPE)
#define ETL_USING_BUILTIN_UNDERLYING_TYPE 0
#endif

namespace etl
{
namespace traits
Expand Down
35 changes: 35 additions & 0 deletions include/etl/type_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -2295,6 +2295,41 @@ typedef integral_constant<bool, true> true_type;
using type_identity_t = typename type_identity<T>::type;
#endif

#if ETL_USING_BUILTIN_UNDERLYING_TYPE
namespace private_type_traits
{
template <typename T, bool = is_enum<T>::value>
struct __underlying_type_impl;

template <typename T>
struct __underlying_type_impl<T, false>
{
};

template <typename T>
struct __underlying_type_impl<T, true>
{
using type = __underlying_type(T);
};
}

template <typename T>
struct underlying_type : private_type_traits::__underlying_type_impl<T, is_enum<T>::value>
{
};

#if ETL_USING_CPP11
template <typename T>
using underlying_type_t = typename underlying_type<T>::type;

template <typename T>
ETL_CONSTEXPR underlying_type_t<T> to_underlying(T val) ETL_NOEXCEPT
{
return static_cast<underlying_type_t<T>>(val);
}
#endif
#endif

#if ETL_USING_CPP11
//*********************************************
// has_duplicates
Expand Down
42 changes: 41 additions & 1 deletion test/test_type_traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1329,11 +1329,51 @@ namespace
}

//*************************************************************************
TEST(test_type_identity)
TEST(test_type_identity)
{
CHECK_CLOSE(type_identity_test_add(1.5f, 2), 3.5f, 0.01f);
}

//*************************************************************************
#if ETL_USING_BUILTIN_UNDERLYING_TYPE
TEST(test_underlying_type)
{
enum enum0_t : char
{
};

enum enum1_t : uint32_t
{
};

enum class enum2_t : short
{
};

enum class enum3_t : size_t
{
};

using enum4_t = enum1_t;
using enum5_t = std::add_const<enum2_t>::type;

CHECK_TRUE((std::is_same<etl::underlying_type<enum0_t>::type, char>::value));
CHECK_TRUE((std::is_same<etl::underlying_type<enum1_t>::type, uint32_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type<enum2_t>::type, short>::value));
CHECK_TRUE((std::is_same<etl::underlying_type<enum3_t>::type, size_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type<enum4_t>::type, uint32_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type<enum5_t>::type, short>::value));
#if ETL_USING_CPP11
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum0_t>, char>::value));
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum1_t>, uint32_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum2_t>, short>::value));
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum3_t>, size_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum4_t>, uint32_t>::value));
CHECK_TRUE((std::is_same<etl::underlying_type_t<enum5_t>, short>::value));
#endif
}
#endif

//*************************************************************************
TEST(test_has_duplicates)
{
Expand Down

0 comments on commit 555d710

Please sign in to comment.