mirror of
https://github.com/ETLCPP/etl.git
synced 2026-10-28 18:07:10 +08:00
Support etl::underlying_type with compiler builtin (#1045)
msvc is unsupported currently Co-authored-by: John Wellbelove <jwellbelove@users.noreply.github.com>
This commit is contained in:
parent
a24977a3db
commit
f69da8577e
@ -2352,6 +2352,35 @@ 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;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// has_duplicates
|
||||
|
||||
@ -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?
|
||||
@ -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.
|
||||
@ -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
|
||||
|
||||
@ -2345,6 +2345,35 @@ 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;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ETL_USING_CPP11
|
||||
//*********************************************
|
||||
// has_duplicates
|
||||
|
||||
@ -134,6 +134,14 @@ namespace etl
|
||||
using forward_like_t = decltype(etl::forward_like<T>(etl::declval<U&>()));
|
||||
#endif
|
||||
|
||||
#if ETL_USING_BUILTIN_UNDERLYING_TYPE && ETL_USING_CPP11
|
||||
template <typename T>
|
||||
ETL_CONSTEXPR underlying_type_t<T> to_underlying(T val) ETL_NOEXCEPT
|
||||
{
|
||||
return static_cast<underlying_type_t<T>>(val);
|
||||
}
|
||||
#endif
|
||||
|
||||
// We can't have std::swap and etl::swap templates coexisting in the unit tests
|
||||
// as the compiler will be unable to decide which one to use, due to ADL.
|
||||
#if ETL_NOT_USING_STL && !defined(ETL_IN_UNIT_TEST)
|
||||
|
||||
@ -1364,6 +1364,46 @@ namespace
|
||||
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)
|
||||
{
|
||||
|
||||
@ -719,6 +719,49 @@ namespace
|
||||
CHECK_EQUAL(forward_like_call_type::ConstRValue, template_function_fl<const TFL&&>(etl::move(u4)));
|
||||
}
|
||||
|
||||
#if ETL_USING_BUILTIN_UNDERLYING_TYPE && ETL_USING_CPP11
|
||||
TEST(test_to_underlying)
|
||||
{
|
||||
enum enum0_t : char
|
||||
{
|
||||
a0 = 'e',
|
||||
a1 = 't',
|
||||
a2 = 'l',
|
||||
a3 = '3'
|
||||
};
|
||||
|
||||
enum enum1_t : uint32_t
|
||||
{
|
||||
b0 = 2,
|
||||
b1 = 3,
|
||||
b2 = 5,
|
||||
};
|
||||
|
||||
enum enum2_t : signed
|
||||
{
|
||||
c0 = -2,
|
||||
c1 = 100,
|
||||
};
|
||||
|
||||
using enum3_t = enum1_t;
|
||||
|
||||
enum0_t e0 = enum0_t::a1;
|
||||
enum1_t e1 = enum1_t::b2;
|
||||
enum2_t e2 = enum2_t::c0;
|
||||
enum3_t e3 = enum3_t::b0;
|
||||
|
||||
CHECK_EQUAL(etl::to_underlying(e0), 't');
|
||||
CHECK_EQUAL(etl::to_underlying(e1), 5);
|
||||
CHECK_EQUAL(etl::to_underlying(e2), -2);
|
||||
CHECK_EQUAL(etl::to_underlying(e3), 2);
|
||||
CHECK_EQUAL(etl::to_underlying(enum0_t::a0), 'e');
|
||||
CHECK_EQUAL(etl::to_underlying(enum0_t::a2), 'l');
|
||||
CHECK_EQUAL(etl::to_underlying(enum0_t::a3), '3');
|
||||
CHECK_EQUAL(etl::to_underlying(enum3_t::b1), 3);
|
||||
CHECK_EQUAL(etl::to_underlying(enum2_t::c1), 100);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ETL_HAS_PACKED
|
||||
//*********************************
|
||||
TEST(test_packed)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user