fork download
  1. #include <tr1/type_traits>
  2. #include <type_traits>
  3.  
  4. namespace detail {
  5. using namespace std::tr1;
  6.  
  7. template <typename T> struct promote { typedef T type; };
  8. template <> struct promote<bool> { typedef int type; };
  9. template <> struct promote<char> { typedef int type; };
  10. template <> struct promote<signed char> { typedef int type; };
  11. template <> struct promote<unsigned char> { typedef int type; };
  12. template <> struct promote<short> { typedef int type; };
  13. template <> struct promote<unsigned short> { typedef int type; };
  14.  
  15. template <typename> struct rank;
  16. template <> struct rank<int> { enum { value = 0 }; };
  17. template <> struct rank<unsigned> { enum { value = 0 }; };
  18. template <> struct rank<long> { enum { value = 1 }; };
  19. template <> struct rank<unsigned long> { enum { value = 1 }; };
  20. template <> struct rank<long long> { enum { value = 2 }; };
  21. template <> struct rank<unsigned long long> { enum { value = 2 }; };
  22. template <> struct rank<float> { enum { value = 3 }; };
  23. template <> struct rank<double> { enum { value = 4 }; };
  24. template <> struct rank<long double> { enum { value = 5 }; };
  25.  
  26. template <typename> struct make_unsigned;
  27. template <> struct make_unsigned<int> { typedef unsigned type; };
  28. template <> struct make_unsigned<long> { typedef unsigned long type; };
  29. template <> struct make_unsigned<long long> { typedef unsigned long long type; };
  30.  
  31. template < typename A
  32. , typename B
  33. , bool Is_fp_or_same_signs_or_A_is_unsigned_or_bigger >
  34. struct common_type_impl {
  35. typedef A type;
  36. };
  37. template <typename A, typename B>
  38. struct common_type_impl<A, B, false>
  39. : make_unsigned<A> {};
  40.  
  41. template <typename A, typename B, bool A_is_higher>
  42. struct common_type_swap
  43. : common_type_impl< A
  44. , B
  45. , is_floating_point<A>::value || is_floating_point<B>::value
  46. || (is_signed<A>::value == is_signed<B>::value)
  47. || is_unsigned<A>::value || (sizeof(A) > sizeof(B))
  48. > {};
  49. template <typename A, typename B>
  50. struct common_type_swap<A, B, false>
  51. : common_type_swap<B, A, true> {};
  52.  
  53. template <typename A, typename B>
  54. struct common_type
  55. : common_type_swap<A, B, (rank<A>::value > rank<B>::value)> {};
  56. }
  57.  
  58. template <typename A, typename B>
  59. struct common_type
  60. : detail::common_type< typename detail::promote<A>::type
  61. , typename detail::promote<B>::type > {};
  62.  
  63. template <typename A, typename B>
  64. void test() {
  65. using common_type = typename common_type<A, B>::type;
  66. using sum_type = decltype(A{} + B{});
  67. static_assert(std::is_same<common_type, sum_type>{}, "");
  68. };
  69. template <typename T>
  70. void test2() {
  71. test<T, bool>();
  72. test<T, char>();
  73. test<T, signed char>();
  74. test<T, unsigned char>();
  75. test<T, short>();
  76. test<T, unsigned short>();
  77. test<T, int>();
  78. test<T, unsigned>();
  79. test<T, long>();
  80. test<T, unsigned long>();
  81. test<T, long long>();
  82. test<T, unsigned long long>();
  83. test<T, float>();
  84. test<T, double>();
  85. test<T, long double>();
  86. };
  87. int main() {
  88. test2<bool>();
  89. test2<char>();
  90. test2<signed char>();
  91. test2<unsigned char>();
  92. test2<short>();
  93. test2<unsigned short>();
  94. test2<int>();
  95. test2<unsigned>();
  96. test2<long>();
  97. test2<unsigned long>();
  98. test2<long long>();
  99. test2<unsigned long long>();
  100. test2<float>();
  101. test2<double>();
  102. test2<long double>();
  103. }
Success #stdin #stdout 0s 3136KB
stdin
Standard input is empty
stdout
Standard output is empty