[K/N] Implicit constructors for saturating. ^KT-48537
This commit is contained in:
committed by
Space
parent
03b09346a5
commit
e6b7a142b2
@@ -3,6 +3,8 @@
|
||||
* that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
@@ -11,6 +13,15 @@ namespace kotlin {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <typename From, typename Into>
|
||||
struct is_promotable :
|
||||
public std::bool_constant<
|
||||
std::is_integral_v<From> && std::is_integral_v<Into> && std::is_signed_v<From> == std::is_signed_v<Into> &&
|
||||
sizeof(Into) >= sizeof(From)> {};
|
||||
|
||||
template <typename From, typename Into>
|
||||
inline constexpr bool is_promotable_v = is_promotable<From, Into>::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<int8_t, uint32_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 <typename U>
|
||||
// Implicitly construct from safely promotable types.
|
||||
template <typename U, typename std::enable_if_t<internal::is_promotable_v<U, T>, bool> = false>
|
||||
constexpr saturating(U value) noexcept : value(value) {}
|
||||
|
||||
// Explicitly construct from any integral value using saturating_cast.
|
||||
template <typename U, typename std::enable_if_t<!internal::is_promotable_v<U, T>, bool> = false>
|
||||
explicit constexpr saturating(U value) noexcept : value(saturating_cast<T>(value)) {}
|
||||
|
||||
// Construct from any other saturating type using saturating_cast.
|
||||
template <typename U>
|
||||
// Implicitly construct from safely promotable saturating type.
|
||||
template <typename U, typename std::enable_if_t<internal::is_promotable_v<U, T>, bool> = false>
|
||||
constexpr saturating(saturating<U> other) noexcept : value(other.value) {}
|
||||
|
||||
// Explicitly construct from any saturating type using saturating_cast.
|
||||
template <typename U, typename std::enable_if_t<!internal::is_promotable_v<U, T>, bool> = false>
|
||||
explicit constexpr saturating(saturating<U> other) noexcept : value(saturating_cast<T>(other.value)) {}
|
||||
|
||||
~saturating() = default;
|
||||
@@ -247,6 +266,15 @@ using uint_sat32_t = saturating<uint32_t>;
|
||||
using uint_sat64_t = saturating<uint64_t>;
|
||||
using size_sat_t = saturating<size_t>;
|
||||
|
||||
template <typename T>
|
||||
struct is_saturating : public std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_saturating<saturating<T>> : public std::true_type {};
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_saturating_v = is_saturating<T>::value;
|
||||
|
||||
} // namespace kotlin
|
||||
|
||||
namespace std {
|
||||
|
||||
@@ -122,19 +122,19 @@ inline constexpr bool is_explicitly_convertible_v = !std::is_convertible_v<From,
|
||||
} // namespace
|
||||
|
||||
TEST(SaturatingTest, ValueConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<int8_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int8_t, int_sat8_t>);
|
||||
static_assert(std::is_convertible_v<int8_t, int_sat16_t>);
|
||||
static_assert(std::is_convertible_v<int8_t, int_sat32_t>);
|
||||
static_assert(std::is_convertible_v<int8_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int8_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<int16_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int16_t, int_sat16_t>);
|
||||
static_assert(std::is_convertible_v<int16_t, int_sat32_t>);
|
||||
static_assert(std::is_convertible_v<int16_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int16_t, uint_sat32_t>);
|
||||
@@ -142,8 +142,8 @@ TEST(SaturatingTest, ValueConstructor) {
|
||||
|
||||
static_assert(is_explicitly_convertible_v<int32_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int32_t, int_sat32_t>);
|
||||
static_assert(std::is_convertible_v<int32_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int32_t, uint_sat32_t>);
|
||||
@@ -152,7 +152,7 @@ TEST(SaturatingTest, ValueConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<int64_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int64_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int64_t, uint_sat32_t>);
|
||||
@@ -162,19 +162,19 @@ TEST(SaturatingTest, ValueConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint8_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint8_t, uint_sat8_t>);
|
||||
static_assert(std::is_convertible_v<uint8_t, uint_sat16_t>);
|
||||
static_assert(std::is_convertible_v<uint8_t, uint_sat32_t>);
|
||||
static_assert(std::is_convertible_v<uint8_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint16_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint16_t, uint_sat16_t>);
|
||||
static_assert(std::is_convertible_v<uint16_t, uint_sat32_t>);
|
||||
static_assert(std::is_convertible_v<uint16_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, int_sat16_t>);
|
||||
@@ -182,8 +182,8 @@ TEST(SaturatingTest, ValueConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint32_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint32_t, uint_sat32_t>);
|
||||
static_assert(std::is_convertible_v<uint32_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, int_sat16_t>);
|
||||
@@ -192,7 +192,7 @@ TEST(SaturatingTest, ValueConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint64_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint64_t, uint_sat64_t>);
|
||||
}
|
||||
|
||||
TEST(SaturatingTest, ValueCast) {
|
||||
@@ -271,9 +271,9 @@ TEST(SaturatingTest, ValueCast) {
|
||||
|
||||
TEST(SaturatingTest, SaturatingConstructor) {
|
||||
static_assert(std::is_convertible_v<int_sat8_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int_sat8_t, int_sat16_t>);
|
||||
static_assert(std::is_convertible_v<int_sat8_t, int_sat32_t>);
|
||||
static_assert(std::is_convertible_v<int_sat8_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat8_t, uint_sat32_t>);
|
||||
@@ -281,8 +281,8 @@ TEST(SaturatingTest, SaturatingConstructor) {
|
||||
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, int_sat8_t>);
|
||||
static_assert(std::is_convertible_v<int_sat16_t, int_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int_sat16_t, int_sat32_t>);
|
||||
static_assert(std::is_convertible_v<int_sat16_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat16_t, uint_sat32_t>);
|
||||
@@ -291,7 +291,7 @@ TEST(SaturatingTest, SaturatingConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, int_sat16_t>);
|
||||
static_assert(std::is_convertible_v<int_sat32_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<int_sat32_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<int_sat32_t, uint_sat32_t>);
|
||||
@@ -311,9 +311,9 @@ TEST(SaturatingTest, SaturatingConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint_sat8_t, int_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat8_t, int_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat8_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat8_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat8_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat8_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat8_t, uint_sat16_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat8_t, uint_sat32_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat8_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, int_sat16_t>);
|
||||
@@ -321,8 +321,8 @@ TEST(SaturatingTest, SaturatingConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, int_sat64_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, uint_sat8_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat16_t, uint_sat16_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat16_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat16_t, uint_sat32_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat16_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint_sat32_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat32_t, int_sat16_t>);
|
||||
@@ -331,7 +331,7 @@ TEST(SaturatingTest, SaturatingConstructor) {
|
||||
static_assert(is_explicitly_convertible_v<uint_sat32_t, uint_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat32_t, uint_sat16_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat32_t, uint_sat32_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat32_t, uint_sat64_t>);
|
||||
static_assert(std::is_convertible_v<uint_sat32_t, uint_sat64_t>);
|
||||
|
||||
static_assert(is_explicitly_convertible_v<uint_sat64_t, int_sat8_t>);
|
||||
static_assert(is_explicitly_convertible_v<uint_sat64_t, int_sat16_t>);
|
||||
@@ -553,6 +553,25 @@ TEST(SaturatingTest, CommonTypeWithIntegral) {
|
||||
static_assert(std::is_same_v<std::common_type_t<uint_sat64_t, uint64_t>, uint_sat64_t>);
|
||||
}
|
||||
|
||||
TEST(SaturatingTest, IsSaturating) {
|
||||
static_assert(!is_saturating_v<int8_t>);
|
||||
static_assert(!is_saturating_v<int16_t>);
|
||||
static_assert(!is_saturating_v<int32_t>);
|
||||
static_assert(!is_saturating_v<int64_t>);
|
||||
static_assert(!is_saturating_v<uint8_t>);
|
||||
static_assert(!is_saturating_v<uint16_t>);
|
||||
static_assert(!is_saturating_v<uint32_t>);
|
||||
static_assert(!is_saturating_v<uint64_t>);
|
||||
static_assert(is_saturating_v<int_sat8_t>);
|
||||
static_assert(is_saturating_v<int_sat16_t>);
|
||||
static_assert(is_saturating_v<int_sat32_t>);
|
||||
static_assert(is_saturating_v<int_sat64_t>);
|
||||
static_assert(is_saturating_v<uint_sat8_t>);
|
||||
static_assert(is_saturating_v<uint_sat16_t>);
|
||||
static_assert(is_saturating_v<uint_sat32_t>);
|
||||
static_assert(is_saturating_v<uint_sat64_t>);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user