fork download
  1.  
  2. #include <cmath>
  3. #include <cstdint>
  4. #include <iomanip>
  5. #include <iostream>
  6. #include <limits>
  7.  
  8. // the upper bound must always be checked
  9. template <typename target_type, typename actual_type>
  10. constexpr bool test_upper_bound(const actual_type n)
  11. {
  12. typedef typename std::common_type<target_type, actual_type>::type common_type;
  13. const auto c_n = static_cast<common_type>(n);
  14. const auto t_max = static_cast<common_type>(std::numeric_limits<target_type>::max());
  15. return (c_n <= t_max);
  16. }
  17.  
  18. // the lower bound is only needed to be checked explicitely in non-trivial cases, see the next three functions
  19. template <typename target_type, typename actual_type>
  20. constexpr typename std::enable_if<!(std::is_unsigned<target_type>::value) && !(std::is_unsigned<actual_type>::value), bool>::type
  21. test_lower_bound(const actual_type n)
  22. {
  23. typedef typename std::common_type<target_type, actual_type>::type common_type;
  24. const auto c_n = static_cast<common_type>(n);
  25. const auto t_min_as_t = std::numeric_limits<target_type>::lowest();
  26. const auto t_min = static_cast<common_type>(t_min_as_t);
  27. return (c_n >= t_min);
  28. }
  29.  
  30. // for signed target types where the actual type is unsigned, the lower bound is trivially satisfied.
  31. template <typename target_type, typename actual_type>
  32. constexpr typename std::enable_if<!(std::is_unsigned<target_type>::value) && (std::is_unsigned<actual_type>::value), bool>::type
  33. test_lower_bound(const actual_type n)
  34. {
  35. return true;
  36. }
  37.  
  38. // for unsigned target types, the sign of n musn't be negative
  39. // but that's not an issue with unsigned actual_type
  40. template <typename target_type, typename actual_type>
  41. constexpr typename std::enable_if<std::is_integral<target_type>::value &&
  42. std::is_unsigned<target_type>::value &&
  43. std::is_integral<actual_type>::value &&
  44. std::is_unsigned<actual_type>::value, bool>::type
  45. test_lower_bound(const actual_type)
  46. {
  47. return true;
  48. }
  49.  
  50. // for unsigned target types, the sign of n musn't be negative
  51. template <typename target_type, typename actual_type>
  52. constexpr typename std::enable_if<std::is_integral<target_type>::value &&
  53. std::is_unsigned<target_type>::value &&
  54. (!std::is_integral<actual_type>::value ||
  55. !std::is_unsigned<actual_type>::value), bool>::type
  56. test_lower_bound(const actual_type n)
  57. {
  58. return (n >= 0);
  59. }
  60.  
  61. // value may be integral if the target type is non-integral
  62. template <typename target_type, typename actual_type>
  63. constexpr typename std::enable_if<!std::is_integral<target_type>::value, bool>::type
  64. test_integrality(const actual_type)
  65. {
  66. return true;
  67. }
  68.  
  69. // value must be integral if the target type is integral
  70. template <typename target_type, typename actual_type>
  71. constexpr typename std::enable_if<std::is_integral<target_type>::value, bool>::type
  72. test_integrality(const actual_type n)
  73. {
  74. return ( (std::abs(n - std::floor(n)) < 1e-8) || (std::abs(n - std::ceil(n)) < 1e-8) );
  75. }
  76.  
  77. // perform check only if non-trivial
  78. template <typename target_type, typename actual_type>
  79. constexpr typename std::enable_if<!std::is_same<target_type, actual_type>::value, bool>::type
  80. CanTypeFitValue(const actual_type n)
  81. {
  82. return test_upper_bound<target_type>(n) &&
  83. test_lower_bound<target_type>(n) &&
  84. test_integrality<target_type>(n);
  85. }
  86.  
  87.  
  88. // trivial case: actual_type == target_type
  89. template <typename actual_type>
  90. constexpr bool CanTypeFitValue(const actual_type)
  91. {
  92. return true;
  93. }
  94.  
  95. int main()
  96. {
  97. int ns[] = {6, 1203032847, 2394857, -13423, 9324, -192992929};
  98. for ( const auto n : ns )
  99. {
  100. std::cout << std::setw(10) << n << "\t";
  101. std::cout << " " << CanTypeFitValue<int8_t>(n);
  102. std::cout << " " << CanTypeFitValue<uint8_t>(n);
  103. std::cout << " " << CanTypeFitValue<int16_t>(n);
  104. std::cout << " " << CanTypeFitValue<uint16_t>(n);
  105. std::cout << " " << CanTypeFitValue<int32_t>(n);
  106. std::cout << " " << CanTypeFitValue<uint32_t>(n);
  107. std::cout << " " << CanTypeFitValue<int64_t>(n);
  108. std::cout << " " << CanTypeFitValue<uint64_t>(n);
  109. std::cout << " " << CanTypeFitValue<float>(n);
  110. std::cout << " " << CanTypeFitValue<double>(n);
  111. std::cout << "\n";
  112. }
  113. std::cout << "\n";
  114. unsigned long long uss[] = {6, 1201146189143ull, 2397, 23};
  115. for ( const auto n : uss )
  116. {
  117. std::cout << std::setw(10) << n << "\t";
  118. std::cout << " " << CanTypeFitValue<int8_t>(n);
  119. std::cout << " " << CanTypeFitValue<uint8_t>(n);
  120. std::cout << " " << CanTypeFitValue<int16_t>(n);
  121. std::cout << " " << CanTypeFitValue<uint16_t>(n);
  122. std::cout << " " << CanTypeFitValue<int32_t>(n);
  123. std::cout << " " << CanTypeFitValue<uint32_t>(n);
  124. std::cout << " " << CanTypeFitValue<int64_t>(n);
  125. std::cout << " " << CanTypeFitValue<uint64_t>(n);
  126. std::cout << " " << CanTypeFitValue<float>(n);
  127. std::cout << " " << CanTypeFitValue<double>(n);
  128. std::cout << "\n";
  129. }
  130. std::cout << "\n";
  131. float fs[] = {0.0, 0.5, -0.5, 1.0, -1.0, 1e10, -1e10};
  132. for ( const auto f : fs )
  133. {
  134. std::cout << std::setw(10) << f << "\t";
  135. std::cout << " " << CanTypeFitValue<int8_t>(f);
  136. std::cout << " " << CanTypeFitValue<uint8_t>(f);
  137. std::cout << " " << CanTypeFitValue<int16_t>(f);
  138. std::cout << " " << CanTypeFitValue<uint16_t>(f);
  139. std::cout << " " << CanTypeFitValue<int32_t>(f);
  140. std::cout << " " << CanTypeFitValue<uint32_t>(f);
  141. std::cout << " " << CanTypeFitValue<int64_t>(f);
  142. std::cout << " " << CanTypeFitValue<uint64_t>(f);
  143. std::cout << " " << CanTypeFitValue<float>(f);
  144. std::cout << " " << CanTypeFitValue<double>(f);
  145. std::cout << "\n";
  146. }
  147. }
  148.  
Success #stdin #stdout 0s 5504KB
stdin
Standard input is empty
stdout
         6	 1 1 1 1 1 1 1 1 1 1
1203032847	 0 0 0 0 1 1 1 1 1 1
   2394857	 0 0 0 0 1 1 1 1 1 1
    -13423	 0 0 1 0 1 0 1 0 1 1
      9324	 0 0 1 1 1 1 1 1 1 1
-192992929	 0 0 0 0 1 0 1 0 1 1

         6	 1 1 1 1 1 1 1 1 1 1
1201146189143	 0 0 0 0 0 0 1 1 1 1
      2397	 0 0 1 1 1 1 1 1 1 1
        23	 1 1 1 1 1 1 1 1 1 1

         0	 1 1 1 1 1 1 1 1 1 1
       0.5	 0 0 0 0 0 0 0 0 1 1
      -0.5	 0 0 0 0 0 0 0 0 1 1
         1	 1 1 1 1 1 1 1 1 1 1
        -1	 1 0 1 0 1 0 1 0 1 1
     1e+10	 0 0 0 0 0 0 1 1 1 1
    -1e+10	 0 0 0 0 0 0 1 0 1 1