diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index 260e3cda0..79f1b78aa 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -36,16 +36,7 @@ namespace Nz template void HashCombine(std::size_t& seed, const T& v); template bool IsPowerOfTwo(T value); template T ReverseBits(T integer); -#ifdef NAZARA_DEBUG - template && std::is_integral_v, int> = 0> To SafeCast(From value); - template && std::is_floating_point_v, int> = 0> To SafeCast(From value); - template && std::is_floating_point_v, int> = 0> To SafeCast(From value); - template && std::is_integral_v, int> = 0> To SafeCast(From value); - template&& std::is_integral_v, int> = 0> To SafeCast(From value); - template&& std::is_enum_v, int> = 0> To SafeCast(From value); -#else template To SafeCast(From value); -#endif template constexpr auto UnderlyingCast(T value) -> std::underlying_type_t; template diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 4a198b47d..b37fee294 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -293,74 +293,85 @@ namespace Nz return reversed; } -#ifdef NAZARA_DEBUG - template && std::is_integral_v, int>> - To SafeCast(From value) - { - // Type capable of storing the biggest value between the two types - using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v)), From, To>; - // Type capable of storing the smallest value between the two types - using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v)), From, To>; - - if constexpr (!std::is_signed_v) - assert(value >= 0); - - assert(static_cast(value) <= static_cast(std::numeric_limits::max())); - assert(static_cast(value) >= static_cast(std::numeric_limits::lowest())); - - return static_cast(value); - } - - template && std::is_floating_point_v, int>> - To SafeCast(From value) - { - // Type capable of storing the biggest value between the two types - using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>; - // Type capable of storing the smallest value between the two types - using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>; - - assert(static_cast(value) <= static_cast(std::numeric_limits::max())); - assert(static_cast(value) >= static_cast(std::numeric_limits::lowest())); - - return static_cast(value); - } - - template && std::is_floating_point_v, int>> - To SafeCast(From value) - { - assert(std::floor(value) == value); - - assert(value <= static_cast(std::numeric_limits::max())); - assert(value >= static_cast(std::numeric_limits::lowest())); - - return static_cast(value); - } - - template && std::is_integral_v, int>> - To SafeCast(From value) - { - return static_cast(value); - } - - template && std::is_integral_v, int>> - To SafeCast(From value) - { - return static_cast(SafeCast>(value)); - } - - template && std::is_enum_v, int>> - To SafeCast(From value) - { - return SafeCast(static_cast>(value)); - } - -#else template To SafeCast(From value) { +#if defined(NAZARA_DEBUG) && !defined(NDEBUG) + if constexpr (std::is_integral_v) + { + if constexpr (std::is_enum_v) + { + return SafeCast(static_cast>(value)); + } + else if constexpr (std::is_floating_point_v) + { + assert(std::floor(value) == value); + + assert(value <= static_cast(std::numeric_limits::max())); + assert(value >= static_cast(std::numeric_limits::lowest())); + } + else if constexpr (std::is_integral_v) + { + // Type capable of storing the biggest value between the two types + using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v)), From, To>; + // Type capable of storing the smallest value between the two types + using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To) || (sizeof(From) == sizeof(To) && std::is_signed_v)), From, To>; + + if constexpr (!std::is_signed_v) + assert(value >= 0); + + assert(static_cast(value) <= static_cast(std::numeric_limits::max())); + assert(static_cast(value) >= static_cast(std::numeric_limits::lowest())); + } + } + else if constexpr (std::is_enum_v) + { + return static_cast(SafeCast>(value)); + } + else if constexpr (std::is_floating_point_v) + { + if constexpr (std::is_floating_point_v) + { + // Type capable of storing the biggest value between the two types + using MaxValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>; + // Type capable of storing the smallest value between the two types + using MinValueType = std::conditional_t<(sizeof(From) > sizeof(To)), From, To>; + + assert(static_cast(value) <= static_cast(std::numeric_limits::max())); + assert(static_cast(value) >= static_cast(std::numeric_limits::lowest())); + } + } + else if constexpr (std::is_reference_v) + { + if constexpr (std::is_reference_v) + { + using BaseFromType = std::remove_reference_t>; + using BaseToType = std::remove_reference_t>; + + if constexpr (!std::is_same_v && std::is_base_of_v && std::is_polymorphic_v) + { + using ToPtr = std::add_pointer_t>; + assert(dynamic_cast(&value) != nullptr); + } + } + } + else if constexpr (std::is_pointer_v) + { + if constexpr (std::is_pointer_v) + { + using BaseFromType = std::remove_pointer_t>; + using BaseToType = std::remove_pointer_t>; + + if constexpr (!std::is_same_v && std::is_base_of_v && std::is_polymorphic_v) + { + assert(dynamic_cast(value) != nullptr); + } + } + } +#endif + return static_cast(value); } -#endif template constexpr auto UnderlyingCast(T value) -> std::underlying_type_t