debug_less.pass.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is dual licensed under the MIT and the University of Illinois Open
  6. // Source Licenses. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. // UNSUPPORTED: libcpp-no-exceptions
  10. // <algorithm>
  11. // template <class _Compare> struct __debug_less
  12. // __debug_less checks that a comparator actually provides a strict-weak ordering.
  13. struct DebugException {};
  14. #define _LIBCPP_DEBUG 0
  15. #define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : throw ::DebugException())
  16. #include <algorithm>
  17. #include <cassert>
  18. template <int ID>
  19. struct MyType {
  20. int value;
  21. explicit MyType(int xvalue = 0) : value(xvalue) {}
  22. };
  23. template <int ID1, int ID2>
  24. bool operator<(MyType<ID1> const& LHS, MyType<ID2> const& RHS) {
  25. return LHS.value < RHS.value;
  26. }
  27. struct CompareBase {
  28. static int called;
  29. static void reset() {
  30. called = 0;
  31. }
  32. };
  33. int CompareBase::called = 0;
  34. template <class ValueType>
  35. struct GoodComparator : public CompareBase {
  36. bool operator()(ValueType const& lhs, ValueType const& rhs) const {
  37. ++CompareBase::called;
  38. return lhs < rhs;
  39. }
  40. };
  41. template <class ValueType>
  42. struct BadComparator : public CompareBase {
  43. bool operator()(ValueType const&, ValueType const&) const {
  44. ++CompareBase::called;
  45. return true;
  46. }
  47. };
  48. template <class T1, class T2>
  49. struct TwoWayHomoComparator : public CompareBase {
  50. bool operator()(T1 const& lhs, T2 const& rhs) const {
  51. ++CompareBase::called;
  52. return lhs < rhs;
  53. }
  54. bool operator()(T2 const& lhs, T1 const& rhs) const {
  55. ++CompareBase::called;
  56. return lhs < rhs;
  57. }
  58. };
  59. template <class T1, class T2>
  60. struct OneWayHomoComparator : public CompareBase {
  61. bool operator()(T1 const& lhs, T2 const& rhs) const {
  62. ++CompareBase::called;
  63. return lhs < rhs;
  64. }
  65. };
  66. using std::__debug_less;
  67. typedef MyType<0> MT0;
  68. typedef MyType<1> MT1;
  69. void test_passing() {
  70. int& called = CompareBase::called;
  71. called = 0;
  72. MT0 one(1);
  73. MT0 two(2);
  74. MT1 three(3);
  75. MT1 four(4);
  76. {
  77. typedef GoodComparator<MT0> C;
  78. typedef __debug_less<C> D;
  79. C c;
  80. D d(c);
  81. assert(d(one, two) == true);
  82. assert(called == 2);
  83. called = 0;
  84. assert(d(one, one) == false);
  85. assert(called == 1);
  86. called = 0;
  87. assert(d(two, one) == false);
  88. assert(called == 1);
  89. called = 0;
  90. }
  91. {
  92. typedef TwoWayHomoComparator<MT0, MT1> C;
  93. typedef __debug_less<C> D;
  94. C c;
  95. D d(c);
  96. assert(d(one, three) == true);
  97. assert(called == 2);
  98. called = 0;
  99. assert(d(three, one) == false);
  100. assert(called == 1);
  101. called = 0;
  102. }
  103. {
  104. typedef OneWayHomoComparator<MT0, MT1> C;
  105. typedef __debug_less<C> D;
  106. C c;
  107. D d(c);
  108. assert(d(one, three) == true);
  109. assert(called == 1);
  110. called = 0;
  111. }
  112. }
  113. void test_failing() {
  114. int& called = CompareBase::called;
  115. called = 0;
  116. MT0 one(1);
  117. MT0 two(2);
  118. {
  119. typedef BadComparator<MT0> C;
  120. typedef __debug_less<C> D;
  121. C c;
  122. D d(c);
  123. try {
  124. d(one, two);
  125. assert(false);
  126. } catch (DebugException const&) {
  127. }
  128. assert(called == 2);
  129. called = 0;
  130. }
  131. }
  132. template <int>
  133. struct Tag {
  134. explicit Tag(int v) : value(v) {}
  135. int value;
  136. };
  137. template <class = void>
  138. struct FooImp {
  139. explicit FooImp(int x) : x_(x) {}
  140. int x_;
  141. };
  142. template <class T>
  143. inline bool operator<(FooImp<T> const& x, Tag<0> y) {
  144. return x.x_ < y.value;
  145. }
  146. template <class T>
  147. inline bool operator<(Tag<0>, FooImp<T> const&) {
  148. static_assert(sizeof(FooImp<T>) != sizeof(FooImp<T>), "should not be instantiated");
  149. }
  150. template <class T>
  151. inline bool operator<(Tag<1> x, FooImp<T> const& y) {
  152. return x.value < y.x_;
  153. }
  154. template <class T>
  155. inline bool operator<(FooImp<T> const&, Tag<1>) {
  156. static_assert(sizeof(FooImp<T>) != sizeof(FooImp<T>), "should not be instantiated");
  157. }
  158. typedef FooImp<> Foo;
  159. // Test that we don't attempt to call the comparator with the arguments reversed
  160. // for upper_bound and lower_bound since the comparator or type is not required
  161. // to support it, nor does it require the range to have a strict weak ordering.
  162. // See llvm.org/PR39458
  163. void test_upper_and_lower_bound() {
  164. Foo table[] = {Foo(1), Foo(2), Foo(3), Foo(4), Foo(5)};
  165. {
  166. Foo* iter = std::lower_bound(std::begin(table), std::end(table), Tag<0>(3));
  167. assert(iter == (table + 2));
  168. }
  169. {
  170. Foo* iter = std::upper_bound(std::begin(table), std::end(table), Tag<1>(3));
  171. assert(iter == (table + 3));
  172. }
  173. }
  174. int main() {
  175. test_passing();
  176. test_failing();
  177. test_upper_and_lower_bound();
  178. }