xcompare.hpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /***************************************************************************
  2. * Copyright (c) QuantStack *
  3. * *
  4. * Distributed under the terms of the BSD 3-Clause License. *
  5. * *
  6. * The full license is in the file LICENSE, distributed with this software. *
  7. ****************************************************************************/
  8. #ifndef XTL_COMPARE_HPP
  9. #define XTL_COMPARE_HPP
  10. #include <type_traits>
  11. namespace xtl
  12. {
  13. /**
  14. * @defgroup xtl_xcompare
  15. *
  16. * Compare the values of two integers t and u. Unlike builtin comparison operators,
  17. * negative signed integers always compare less than (and not equal to) unsigned integers.
  18. */
  19. namespace detail
  20. {
  21. template <class T, class U>
  22. struct same_signedness :
  23. std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value>
  24. {
  25. };
  26. template <
  27. class T,
  28. class U,
  29. std::enable_if_t<same_signedness<T, U>::value, bool> = true
  30. >
  31. constexpr bool cmp_equal_impl(T t, U u) noexcept
  32. {
  33. return t == u;
  34. }
  35. template <
  36. class T,
  37. class U,
  38. std::enable_if_t<
  39. !same_signedness<T, U>::value && std::is_signed<T>::value,
  40. bool
  41. > = true
  42. >
  43. constexpr bool cmp_equal_impl(T t, U u) noexcept
  44. {
  45. using UT = std::make_unsigned_t<T>;
  46. return t < 0 ? false : static_cast<UT>(t) == u;
  47. }
  48. template <
  49. class T,
  50. class U,
  51. std::enable_if_t<
  52. !same_signedness<T, U>::value && !std::is_signed<T>::value,
  53. bool
  54. > = true
  55. >
  56. constexpr bool cmp_equal_impl(T t, U u) noexcept
  57. {
  58. using UU = std::make_unsigned_t<U>;
  59. return u < 0 ? false : t == static_cast<UU>(u);
  60. }
  61. }
  62. /**
  63. * ``true`` if @p t is equal to @p u.
  64. *
  65. * @ingroup xtl_xcompare
  66. */
  67. template <class T, class U>
  68. constexpr bool cmp_equal(T t, U u) noexcept
  69. {
  70. return detail::cmp_equal_impl(t, u);
  71. }
  72. /**
  73. * ``true`` if @p t is not equal to @p u.
  74. *
  75. * @ingroup xtl_xcompare
  76. */
  77. template <class T, class U>
  78. constexpr bool cmp_not_equal(T t, U u) noexcept
  79. {
  80. return !cmp_equal(t, u);
  81. }
  82. namespace detail
  83. {
  84. template <
  85. class T,
  86. class U,
  87. std::enable_if_t<detail::same_signedness<T, U>::value, bool> = true
  88. >
  89. constexpr bool cmp_less_impl(T t, U u) noexcept
  90. {
  91. return t < u;
  92. }
  93. template <
  94. class T,
  95. class U,
  96. std::enable_if_t<
  97. !detail::same_signedness<T, U>::value && std::is_signed<T>::value,
  98. bool
  99. > = true
  100. >
  101. constexpr bool cmp_less_impl(T t, U u) noexcept
  102. {
  103. using UT = std::make_unsigned_t<T>;
  104. return t < 0 ? true : static_cast<UT>(t) < u;
  105. }
  106. template <
  107. class T,
  108. class U,
  109. std::enable_if_t<
  110. !detail::same_signedness<T, U>::value && !std::is_signed<T>::value,
  111. bool
  112. > = true
  113. >
  114. constexpr bool cmp_less_impl(T t, U u) noexcept
  115. {
  116. using UU = std::make_unsigned_t<U>;
  117. return u < 0 ? false : t < static_cast<UU>(u);
  118. }
  119. }
  120. /**
  121. * ``true`` if @p t is striclty less than @p u.
  122. *
  123. * @ingroup xtl_xcompare
  124. */
  125. template <class T, class U>
  126. constexpr bool cmp_less(T t, U u) noexcept
  127. {
  128. return detail::cmp_less_impl(t, u);
  129. }
  130. /**
  131. * ``true`` if @p t is striclty greater than @p u.
  132. *
  133. * @ingroup xtl_xcompare
  134. */
  135. template <class T, class U>
  136. constexpr bool cmp_greater(T t, U u) noexcept
  137. {
  138. return cmp_less(u, t);
  139. }
  140. /**
  141. * ``true`` if @p t is less or equal to @p u.
  142. *
  143. * @ingroup xtl_xcompare
  144. */
  145. template <class T, class U>
  146. constexpr bool cmp_less_equal(T t, U u) noexcept
  147. {
  148. return !cmp_greater(t, u);
  149. }
  150. /**
  151. * ``true`` if @p t is greater or equal to @p u.
  152. *
  153. * @ingroup xtl_xcompare
  154. */
  155. template <class T, class U>
  156. constexpr bool cmp_greater_equal(T t, U u) noexcept
  157. {
  158. return !cmp_less(t, u);
  159. }
  160. }
  161. #endif