traits_test.cc (4546B)
1 // Copyright 2017 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/random/internal/traits.h" 16 17 #include <cstdint> 18 #include <type_traits> 19 20 #include "gtest/gtest.h" 21 22 namespace { 23 24 using absl::random_internal::is_widening_convertible; 25 26 // CheckWideningConvertsToSelf<T1, T2, ...>() 27 // 28 // For each type T, checks: 29 // - T IS widening-convertible to itself. 30 // 31 template <typename T> 32 void CheckWideningConvertsToSelf() { 33 static_assert(is_widening_convertible<T, T>::value, 34 "Type is not convertible to self!"); 35 } 36 37 template <typename T, typename Next, typename... Args> 38 void CheckWideningConvertsToSelf() { 39 CheckWideningConvertsToSelf<T>(); 40 CheckWideningConvertsToSelf<Next, Args...>(); 41 } 42 43 // CheckNotWideningConvertibleWithSigned<T1, T2, ...>() 44 // 45 // For each unsigned-type T, checks that: 46 // - T is NOT widening-convertible to Signed(T) 47 // - Signed(T) is NOT widening-convertible to T 48 // 49 template <typename T> 50 void CheckNotWideningConvertibleWithSigned() { 51 using signed_t = typename std::make_signed<T>::type; 52 53 static_assert(!is_widening_convertible<T, signed_t>::value, 54 "Unsigned type is convertible to same-sized signed-type!"); 55 static_assert(!is_widening_convertible<signed_t, T>::value, 56 "Signed type is convertible to same-sized unsigned-type!"); 57 } 58 59 template <typename T, typename Next, typename... Args> 60 void CheckNotWideningConvertibleWithSigned() { 61 CheckNotWideningConvertibleWithSigned<T>(); 62 CheckWideningConvertsToSelf<Next, Args...>(); 63 } 64 65 // CheckWideningConvertsToLargerType<T1, T2, ...>() 66 // 67 // For each successive unsigned-types {Ti, Ti+1}, checks that: 68 // - Ti IS widening-convertible to Ti+1 69 // - Ti IS widening-convertible to Signed(Ti+1) 70 // - Signed(Ti) is NOT widening-convertible to Ti 71 // - Signed(Ti) IS widening-convertible to Ti+1 72 template <typename T, typename Higher> 73 void CheckWideningConvertsToLargerTypes() { 74 using signed_t = typename std::make_signed<T>::type; 75 using higher_t = Higher; 76 using signed_higher_t = typename std::make_signed<Higher>::type; 77 78 static_assert(is_widening_convertible<T, higher_t>::value, 79 "Type not embeddable into larger type!"); 80 static_assert(is_widening_convertible<T, signed_higher_t>::value, 81 "Type not embeddable into larger signed type!"); 82 static_assert(!is_widening_convertible<signed_t, higher_t>::value, 83 "Signed type is embeddable into larger unsigned type!"); 84 static_assert(is_widening_convertible<signed_t, signed_higher_t>::value, 85 "Signed type not embeddable into larger signed type!"); 86 } 87 88 template <typename T, typename Higher, typename Next, typename... Args> 89 void CheckWideningConvertsToLargerTypes() { 90 CheckWideningConvertsToLargerTypes<T, Higher>(); 91 CheckWideningConvertsToLargerTypes<Higher, Next, Args...>(); 92 } 93 94 // CheckWideningConvertsTo<T, U, [expect]> 95 // 96 // Checks that T DOES widening-convert to U. 97 // If "expect" is false, then asserts that T does NOT widening-convert to U. 98 template <typename T, typename U, bool expect = true> 99 void CheckWideningConvertsTo() { 100 static_assert(is_widening_convertible<T, U>::value == expect, 101 "Unexpected result for is_widening_convertible<T, U>!"); 102 } 103 104 TEST(TraitsTest, IsWideningConvertibleTest) { 105 constexpr bool kInvalid = false; 106 107 CheckWideningConvertsToSelf<uint8_t, uint16_t, uint32_t, uint64_t, int8_t, 108 int16_t, int32_t, int64_t, float, double>(); 109 CheckNotWideningConvertibleWithSigned<uint8_t, uint16_t, uint32_t, 110 uint64_t>(); 111 CheckWideningConvertsToLargerTypes<uint8_t, uint16_t, uint32_t, uint64_t>(); 112 113 CheckWideningConvertsTo<float, double>(); 114 CheckWideningConvertsTo<uint16_t, float>(); 115 CheckWideningConvertsTo<uint32_t, double>(); 116 CheckWideningConvertsTo<uint64_t, double, kInvalid>(); 117 CheckWideningConvertsTo<double, float, kInvalid>(); 118 119 CheckWideningConvertsTo<bool, int>(); 120 CheckWideningConvertsTo<bool, float>(); 121 } 122 123 } // namespace