@@ -725,15 +725,16 @@ namespace etl
725
725
{
726
726
// Base case
727
727
template <typename T, typename = int >
728
- struct is_convertible_to_int : false_type
728
+ struct is_convertible_to_int
729
+ : false_type
729
730
{
730
731
};
731
732
732
733
// Selected if `static_cast<int>(declval<T>())` is a valid statement
733
734
// 2nd template argument of base case defaults to int to ensure that this partial specialization is always tried first
734
735
template <typename T>
735
736
struct is_convertible_to_int <T, decltype (static_cast <int >(declval<T>()))>
736
- : true_type
737
+ : true_type
737
738
{
738
739
};
739
740
}
@@ -751,7 +752,29 @@ namespace etl
751
752
template <typename T>
752
753
inline constexpr bool is_enum_v = etl::is_enum<T>::value;
753
754
#endif
755
+ #else
756
+ namespace private_type_traits
757
+ {
758
+ // Helper to detect if a type is convertible to an integer
759
+ template <typename T>
760
+ struct is_convertible_to_int
761
+ {
762
+ static char test (int ); // Match if T is convertible to int
763
+ static double test (...); // Fallback for other types
754
764
765
+ static const bool value = sizeof (test(static_cast <T>(0 ))) == sizeof (char );
766
+ };
767
+ }
768
+
769
+ // Implementation of is_enum
770
+ template <typename T>
771
+ struct is_enum
772
+ {
773
+ static const bool value = private_type_traits::is_convertible_to_int<T>::value &&
774
+ !is_class<T>::value &&
775
+ !is_arithmetic<T>::value &&
776
+ !is_reference<T>::value;
777
+ };
755
778
#endif
756
779
757
780
// ***************************************************************************
@@ -2257,7 +2280,8 @@ typedef integral_constant<bool, true> true_type;
2257
2280
};
2258
2281
2259
2282
template <typename T1, typename T2, typename = void >
2260
- struct common_type_2_impl : decay_conditional_result<const T1&, const T2&>
2283
+ struct common_type_2_impl
2284
+ : decay_conditional_result<const T1&, const T2&>
2261
2285
{
2262
2286
};
2263
2287
@@ -2354,7 +2378,7 @@ typedef integral_constant<bool, true> true_type;
2354
2378
2355
2379
// *********************************************
2356
2380
// underlying_type
2357
-
2381
+ # if ETL_USING_BUILTIN_UNDERLYING_TYPE
2358
2382
// Primary template for etl::underlying_type
2359
2383
template <typename T, bool = etl::is_enum<T>::value>
2360
2384
struct underlying_type ;
@@ -2367,37 +2391,19 @@ typedef integral_constant<bool, true> true_type;
2367
2391
ETL_STATIC_ASSERT (etl::is_enum<T>::value, " etl::underlying_type can only be used with enumeration types." );
2368
2392
};
2369
2393
2370
- #if ETL_USING_BUILTIN_UNDERLYING_TYPE
2371
2394
template <typename T>
2372
2395
struct underlying_type <T, true >
2373
2396
{
2374
2397
typedef __underlying_type (T) type;
2375
2398
};
2376
2399
#else
2400
+ // / Primary template for etl::underlying_type
2401
+ // / Users must spelialise this template for their enumerations.
2377
2402
template <typename T>
2378
- struct underlying_type <T, true >
2403
+ struct underlying_type
2379
2404
{
2380
- private:
2381
-
2382
- // Helper union to deduce the underlying type
2383
- union Helper
2384
- {
2385
- T enum_value;
2386
- unsigned char raw[sizeof (T)];
2387
- };
2388
-
2389
- public:
2390
-
2391
- // The deduced underlying type
2392
- typedef typename etl::conditional<sizeof (Helper) == sizeof (long int ),
2393
- long int ,
2394
- typename etl::conditional<sizeof (Helper) == sizeof (int ),
2395
- int ,
2396
- typename etl::conditional<sizeof (Helper) == sizeof (short ),
2397
- short ,
2398
- typename etl::conditional<sizeof (Helper) == sizeof (char ),
2399
- char ,
2400
- void >::type>::type>::type>::type type;
2405
+ ETL_STATIC_ASSERT (false , " No user defined specialisation of etl::underlying_type for this type" );
2406
+ typedef char type;
2401
2407
};
2402
2408
#endif
2403
2409
0 commit comments