fork(3) 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. 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 to functions
  19. template <typename target_type, typename actual_type>
  20. typename std::enable_if<!(std::is_unsigned<target_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 = static_cast<common_type>(std::numeric_limits<target_type>::lowest());
  26. return ( c_n >= t_min );
  27. }
  28.  
  29. // for unsigned target types, the sign of n musn't be negative
  30. // but that's not an issue with unsigned actual_type
  31. template <typename target_type, typename actual_type>
  32. typename std::enable_if<std::is_integral<target_type>::value &&
  33. std::is_unsigned<target_type>::value &&
  34. std::is_integral<actual_type>::value &&
  35. std::is_unsigned<actual_type>::value, bool>::type
  36. test_lower_bound(const actual_type)
  37. {
  38. return true;
  39. }
  40.  
  41. // for unsigned target types, the sign of n musn't be negative
  42. template <typename target_type, typename actual_type>
  43. typename std::enable_if<std::is_integral<target_type>::value &&
  44. std::is_unsigned<target_type>::value &&
  45. (!std::is_integral<actual_type>::value ||
  46. !std::is_unsigned<actual_type>::value), bool>::type
  47. test_lower_bound(const actual_type n)
  48. {
  49. return ( n >= 0 );
  50. }
  51.  
  52. // value may be integral if the target type is non-integral
  53. template <typename target_type, typename actual_type>
  54. typename std::enable_if<!std::is_integral<target_type>::value, bool>::type
  55. test_integrality(const actual_type)
  56. {
  57. return true;
  58. }
  59.  
  60. // value must be integral if the target type is integral
  61. template <typename target_type, typename actual_type>
  62. typename std::enable_if<std::is_integral<target_type>::value, bool>::type
  63. test_integrality(const actual_type n)
  64. {
  65. return ( (std::abs(n - std::floor(n)) < 1e-8) || (std::abs(n - std::ceil(n)) < 1e-8) );
  66. }
  67.  
  68. // perform check only if non-trivial
  69. template <typename target_type, typename actual_type>
  70. typename std::enable_if<!std::is_same<target_type, actual_type>::value, bool>::type
  71. CanTypeFitValue(const actual_type n)
  72. {
  73. return test_upper_bound<target_type>(n) &&
  74. test_lower_bound<target_type>(n) &&
  75. test_integrality<target_type>(n);
  76. }
  77.  
  78.  
  79. // trivial case: actual_type == target_type
  80. template <typename actual_type>
  81. bool CanTypeFitValue(const actual_type)
  82. {
  83. return true;
  84. }
  85.  
  86. int main()
  87. {
  88. int ns[] = {6, 1203032847, 2394857, -13423, 9324, -192992929};
  89. for ( const auto n : ns )
  90. {
  91. std::cout << std::setw(10) << n << "\t";
  92. std::cout << " " << CanTypeFitValue<int8_t>(n);
  93. std::cout << " " << CanTypeFitValue<uint8_t>(n);
  94. std::cout << " " << CanTypeFitValue<int16_t>(n);
  95. std::cout << " " << CanTypeFitValue<uint16_t>(n);
  96. std::cout << " " << CanTypeFitValue<int32_t>(n);
  97. std::cout << " " << CanTypeFitValue<uint32_t>(n);
  98. std::cout << " " << CanTypeFitValue<int64_t>(n);
  99. std::cout << " " << CanTypeFitValue<uint64_t>(n);
  100. std::cout << " " << CanTypeFitValue<float>(n);
  101. std::cout << " " << CanTypeFitValue<double>(n);
  102. std::cout << "\n";
  103. }
  104. std::cout << "\n";
  105. unsigned long long uss[] = {6, 1201146189143ull, 2397, 23};
  106. for ( const auto n : uss )
  107. {
  108. std::cout << std::setw(10) << n << "\t";
  109. std::cout << " " << CanTypeFitValue<int8_t>(n);
  110. std::cout << " " << CanTypeFitValue<uint8_t>(n);
  111. std::cout << " " << CanTypeFitValue<int16_t>(n);
  112. std::cout << " " << CanTypeFitValue<uint16_t>(n);
  113. std::cout << " " << CanTypeFitValue<int32_t>(n);
  114. std::cout << " " << CanTypeFitValue<uint32_t>(n);
  115. std::cout << " " << CanTypeFitValue<int64_t>(n);
  116. std::cout << " " << CanTypeFitValue<uint64_t>(n);
  117. std::cout << " " << CanTypeFitValue<float>(n);
  118. std::cout << " " << CanTypeFitValue<double>(n);
  119. std::cout << "\n";
  120. }
  121. std::cout << "\n";
  122. float fs[] = {0.0, 0.5, -0.5, 1.0, -1.0, 1e10, -1e10};
  123. for ( const auto f : fs )
  124. {
  125. std::cout << std::setw(10) << f << "\t";
  126. std::cout << " " << CanTypeFitValue<int8_t>(f);
  127. std::cout << " " << CanTypeFitValue<uint8_t>(f);
  128. std::cout << " " << CanTypeFitValue<int16_t>(f);
  129. std::cout << " " << CanTypeFitValue<uint16_t>(f);
  130. std::cout << " " << CanTypeFitValue<int32_t>(f);
  131. std::cout << " " << CanTypeFitValue<uint32_t>(f);
  132. std::cout << " " << CanTypeFitValue<int64_t>(f);
  133. std::cout << " " << CanTypeFitValue<uint64_t>(f);
  134. std::cout << " " << CanTypeFitValue<float>(f);
  135. std::cout << " " << CanTypeFitValue<double>(f);
  136. std::cout << "\n";
  137. }
  138. }
  139.  
Success #stdin #stdout 0s 2860KB
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	 0 1 0 1 0 1 0 1 1 1
1201146189143	 0 0 0 0 0 0 0 1 1 1
      2397	 0 0 0 1 0 1 0 1 1 1
        23	 0 1 0 1 0 1 0 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