From 555d710f706e31751def9e26a1af266c4d5268fd Mon Sep 17 00:00:00 2001 From: "Chiang, Yi" Date: Wed, 5 Mar 2025 11:03:53 +0100 Subject: [PATCH] Support etl::underlying_type with compiler builtin msvc is unsupported currently --- .../etl/generators/type_traits_generator.h | 35 ++++++++++++++++ .../etl/profiles/determine_builtin_support.h | 12 ++++++ include/etl/type_traits.h | 35 ++++++++++++++++ test/test_type_traits.cpp | 42 ++++++++++++++++++- 4 files changed, 123 insertions(+), 1 deletion(-) diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index e55d12217..e09432f60 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2302,6 +2302,41 @@ typedef integral_constant true_type; using type_identity_t = typename type_identity::type; #endif +#if ETL_USING_BUILTIN_UNDERLYING_TYPE +namespace private_type_traits +{ + template ::value> + struct __underlying_type_impl; + + template + struct __underlying_type_impl + { + }; + + template + struct __underlying_type_impl + { + using type = __underlying_type(T); + }; +} + +template +struct underlying_type : private_type_traits::__underlying_type_impl::value> +{ +}; + +#if ETL_USING_CPP11 +template +using underlying_type_t = typename underlying_type::type; + +template +ETL_CONSTEXPR underlying_type_t to_underlying(T val) ETL_NOEXCEPT +{ + return static_cast>(val); +} +#endif +#endif + #if ETL_USING_CPP11 //********************************************* // has_duplicates diff --git a/include/etl/profiles/determine_builtin_support.h b/include/etl/profiles/determine_builtin_support.h index 725927f32..313a18a20 100644 --- a/include/etl/profiles/determine_builtin_support.h +++ b/include/etl/profiles/determine_builtin_support.h @@ -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 diff --git a/include/etl/type_traits.h b/include/etl/type_traits.h index 327f164be..88cf5590c 100644 --- a/include/etl/type_traits.h +++ b/include/etl/type_traits.h @@ -2295,6 +2295,41 @@ typedef integral_constant true_type; using type_identity_t = typename type_identity::type; #endif +#if ETL_USING_BUILTIN_UNDERLYING_TYPE +namespace private_type_traits +{ + template ::value> + struct __underlying_type_impl; + + template + struct __underlying_type_impl + { + }; + + template + struct __underlying_type_impl + { + using type = __underlying_type(T); + }; +} + +template +struct underlying_type : private_type_traits::__underlying_type_impl::value> +{ +}; + +#if ETL_USING_CPP11 +template +using underlying_type_t = typename underlying_type::type; + +template +ETL_CONSTEXPR underlying_type_t to_underlying(T val) ETL_NOEXCEPT +{ + return static_cast>(val); +} +#endif +#endif + #if ETL_USING_CPP11 //********************************************* // has_duplicates diff --git a/test/test_type_traits.cpp b/test/test_type_traits.cpp index 4316a697f..b6466aa53 100644 --- a/test/test_type_traits.cpp +++ b/test/test_type_traits.cpp @@ -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::type; + + CHECK_TRUE((std::is_same::type, char>::value)); + CHECK_TRUE((std::is_same::type, uint32_t>::value)); + CHECK_TRUE((std::is_same::type, short>::value)); + CHECK_TRUE((std::is_same::type, size_t>::value)); + CHECK_TRUE((std::is_same::type, uint32_t>::value)); + CHECK_TRUE((std::is_same::type, short>::value)); +#if ETL_USING_CPP11 + CHECK_TRUE((std::is_same, char>::value)); + CHECK_TRUE((std::is_same, uint32_t>::value)); + CHECK_TRUE((std::is_same, short>::value)); + CHECK_TRUE((std::is_same, size_t>::value)); + CHECK_TRUE((std::is_same, uint32_t>::value)); + CHECK_TRUE((std::is_same, short>::value)); +#endif + } +#endif + //************************************************************************* TEST(test_has_duplicates) {