From e6b7a142b2c5e5eb2f74c9c647e113c6a69a7603 Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Thu, 10 Feb 2022 13:43:46 +0300 Subject: [PATCH] [K/N] Implicit constructors for saturating. ^KT-48537 --- .../runtime/src/main/cpp/Saturating.hpp | 36 +++++++- .../runtime/src/main/cpp/SaturatingTest.cpp | 83 ++++++++++++------- 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/kotlin-native/runtime/src/main/cpp/Saturating.hpp b/kotlin-native/runtime/src/main/cpp/Saturating.hpp index 21ca27e30f9..6c740a43763 100644 --- a/kotlin-native/runtime/src/main/cpp/Saturating.hpp +++ b/kotlin-native/runtime/src/main/cpp/Saturating.hpp @@ -3,6 +3,8 @@ * that can be found in the LICENSE file. */ +#pragma once + #include #include #include @@ -11,6 +13,15 @@ namespace kotlin { namespace internal { +template +struct is_promotable : + public std::bool_constant< + std::is_integral_v && std::is_integral_v && std::is_signed_v == std::is_signed_v && + sizeof(Into) >= sizeof(From)> {}; + +template +inline constexpr bool is_promotable_v = is_promotable::value; + // Not using std::common_type, because it allows to convert between unsigned and signed with losing information, and // is otherwise not intuitive. Examples: // * std::common_type_t is uint32_t - negative numbers are lost. @@ -158,12 +169,20 @@ struct saturating { // The underlying value. T value; - // Construct from any value using saturating_cast. - template + // Implicitly construct from safely promotable types. + template , bool> = false> + constexpr saturating(U value) noexcept : value(value) {} + + // Explicitly construct from any integral value using saturating_cast. + template , bool> = false> explicit constexpr saturating(U value) noexcept : value(saturating_cast(value)) {} - // Construct from any other saturating type using saturating_cast. - template + // Implicitly construct from safely promotable saturating type. + template , bool> = false> + constexpr saturating(saturating other) noexcept : value(other.value) {} + + // Explicitly construct from any saturating type using saturating_cast. + template , bool> = false> explicit constexpr saturating(saturating other) noexcept : value(saturating_cast(other.value)) {} ~saturating() = default; @@ -247,6 +266,15 @@ using uint_sat32_t = saturating; using uint_sat64_t = saturating; using size_sat_t = saturating; +template +struct is_saturating : public std::false_type {}; + +template +struct is_saturating> : public std::true_type {}; + +template +inline constexpr bool is_saturating_v = is_saturating::value; + } // namespace kotlin namespace std { diff --git a/kotlin-native/runtime/src/main/cpp/SaturatingTest.cpp b/kotlin-native/runtime/src/main/cpp/SaturatingTest.cpp index 51e719c4673..4f858699036 100644 --- a/kotlin-native/runtime/src/main/cpp/SaturatingTest.cpp +++ b/kotlin-native/runtime/src/main/cpp/SaturatingTest.cpp @@ -122,19 +122,19 @@ inline constexpr bool is_explicitly_convertible_v = !std::is_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -142,8 +142,8 @@ TEST(SaturatingTest, ValueConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -152,7 +152,7 @@ TEST(SaturatingTest, ValueConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -162,19 +162,19 @@ TEST(SaturatingTest, ValueConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -182,8 +182,8 @@ TEST(SaturatingTest, ValueConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -192,7 +192,7 @@ TEST(SaturatingTest, ValueConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); } TEST(SaturatingTest, ValueCast) { @@ -271,9 +271,9 @@ TEST(SaturatingTest, ValueCast) { TEST(SaturatingTest, SaturatingConstructor) { static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -281,8 +281,8 @@ TEST(SaturatingTest, SaturatingConstructor) { static_assert(is_explicitly_convertible_v); static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -291,7 +291,7 @@ TEST(SaturatingTest, SaturatingConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -311,9 +311,9 @@ TEST(SaturatingTest, SaturatingConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -321,8 +321,8 @@ TEST(SaturatingTest, SaturatingConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -331,7 +331,7 @@ TEST(SaturatingTest, SaturatingConstructor) { static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(std::is_convertible_v); - static_assert(is_explicitly_convertible_v); + static_assert(std::is_convertible_v); static_assert(is_explicitly_convertible_v); static_assert(is_explicitly_convertible_v); @@ -553,6 +553,25 @@ TEST(SaturatingTest, CommonTypeWithIntegral) { static_assert(std::is_same_v, uint_sat64_t>); } +TEST(SaturatingTest, IsSaturating) { + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(!is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); + static_assert(is_saturating_v); +} + namespace { template