git-subtree-dir: third_party/abseil_cpp git-subtree-mainline:ffb2ae54begit-subtree-split:768eb2ca28
		
			
				
	
	
		
			126 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright 2017 The Abseil Authors.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      https://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
#include "absl/random/internal/traits.h"
 | 
						|
 | 
						|
#include <cstdint>
 | 
						|
#include <type_traits>
 | 
						|
 | 
						|
#include "gtest/gtest.h"
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
using absl::random_internal::is_widening_convertible;
 | 
						|
 | 
						|
// CheckWideningConvertsToSelf<T1, T2, ...>()
 | 
						|
//
 | 
						|
// For each type T, checks:
 | 
						|
// - T IS widening-convertible to itself.
 | 
						|
//
 | 
						|
template <typename T>
 | 
						|
void CheckWideningConvertsToSelf() {
 | 
						|
  static_assert(is_widening_convertible<T, T>::value,
 | 
						|
                "Type is not convertible to self!");
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, typename Next, typename... Args>
 | 
						|
void CheckWideningConvertsToSelf() {
 | 
						|
  CheckWideningConvertsToSelf<T>();
 | 
						|
  CheckWideningConvertsToSelf<Next, Args...>();
 | 
						|
}
 | 
						|
 | 
						|
// CheckNotWideningConvertibleWithSigned<T1, T2, ...>()
 | 
						|
//
 | 
						|
// For each unsigned-type T, checks that:
 | 
						|
// - T is NOT widening-convertible to Signed(T)
 | 
						|
// - Signed(T) is NOT widening-convertible to T
 | 
						|
//
 | 
						|
template <typename T>
 | 
						|
void CheckNotWideningConvertibleWithSigned() {
 | 
						|
  using signed_t = typename std::make_signed<T>::type;
 | 
						|
 | 
						|
  static_assert(!is_widening_convertible<T, signed_t>::value,
 | 
						|
                "Unsigned type is convertible to same-sized signed-type!");
 | 
						|
  static_assert(!is_widening_convertible<signed_t, T>::value,
 | 
						|
                "Signed type is convertible to same-sized unsigned-type!");
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, typename Next, typename... Args>
 | 
						|
void CheckNotWideningConvertibleWithSigned() {
 | 
						|
  CheckNotWideningConvertibleWithSigned<T>();
 | 
						|
  CheckWideningConvertsToSelf<Next, Args...>();
 | 
						|
}
 | 
						|
 | 
						|
// CheckWideningConvertsToLargerType<T1, T2, ...>()
 | 
						|
//
 | 
						|
// For each successive unsigned-types {Ti, Ti+1}, checks that:
 | 
						|
// - Ti IS widening-convertible to Ti+1
 | 
						|
// - Ti IS widening-convertible to Signed(Ti+1)
 | 
						|
// - Signed(Ti) is NOT widening-convertible to Ti
 | 
						|
// - Signed(Ti) IS widening-convertible to Ti+1
 | 
						|
template <typename T, typename Higher>
 | 
						|
void CheckWideningConvertsToLargerTypes() {
 | 
						|
  using signed_t = typename std::make_signed<T>::type;
 | 
						|
  using higher_t = Higher;
 | 
						|
  using signed_higher_t = typename std::make_signed<Higher>::type;
 | 
						|
 | 
						|
  static_assert(is_widening_convertible<T, higher_t>::value,
 | 
						|
                "Type not embeddable into larger type!");
 | 
						|
  static_assert(is_widening_convertible<T, signed_higher_t>::value,
 | 
						|
                "Type not embeddable into larger signed type!");
 | 
						|
  static_assert(!is_widening_convertible<signed_t, higher_t>::value,
 | 
						|
                "Signed type is embeddable into larger unsigned type!");
 | 
						|
  static_assert(is_widening_convertible<signed_t, signed_higher_t>::value,
 | 
						|
                "Signed type not embeddable into larger signed type!");
 | 
						|
}
 | 
						|
 | 
						|
template <typename T, typename Higher, typename Next, typename... Args>
 | 
						|
void CheckWideningConvertsToLargerTypes() {
 | 
						|
  CheckWideningConvertsToLargerTypes<T, Higher>();
 | 
						|
  CheckWideningConvertsToLargerTypes<Higher, Next, Args...>();
 | 
						|
}
 | 
						|
 | 
						|
// CheckWideningConvertsTo<T, U, [expect]>
 | 
						|
//
 | 
						|
// Checks that T DOES widening-convert to U.
 | 
						|
// If "expect" is false, then asserts that T does NOT widening-convert to U.
 | 
						|
template <typename T, typename U, bool expect = true>
 | 
						|
void CheckWideningConvertsTo() {
 | 
						|
  static_assert(is_widening_convertible<T, U>::value == expect,
 | 
						|
                "Unexpected result for is_widening_convertible<T, U>!");
 | 
						|
}
 | 
						|
 | 
						|
TEST(TraitsTest, IsWideningConvertibleTest) {
 | 
						|
  constexpr bool kInvalid = false;
 | 
						|
 | 
						|
  CheckWideningConvertsToSelf<
 | 
						|
      uint8_t, uint16_t, uint32_t, uint64_t,
 | 
						|
      int8_t,  int16_t,  int32_t,  int64_t,
 | 
						|
      float,   double>();
 | 
						|
  CheckNotWideningConvertibleWithSigned<
 | 
						|
      uint8_t, uint16_t, uint32_t, uint64_t>();
 | 
						|
  CheckWideningConvertsToLargerTypes<
 | 
						|
      uint8_t, uint16_t, uint32_t, uint64_t>();
 | 
						|
 | 
						|
  CheckWideningConvertsTo<float, double>();
 | 
						|
  CheckWideningConvertsTo<uint16_t, float>();
 | 
						|
  CheckWideningConvertsTo<uint32_t, double>();
 | 
						|
  CheckWideningConvertsTo<uint64_t, double, kInvalid>();
 | 
						|
  CheckWideningConvertsTo<double, float, kInvalid>();
 | 
						|
 | 
						|
  CheckWideningConvertsTo<bool, int>();
 | 
						|
  CheckWideningConvertsTo<bool, float>();
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace
 |