relops.pass.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. // -*- C++ -*-
  2. //===----------------------------------------------------------------------===//
  3. //
  4. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  5. // See https://llvm.org/LICENSE.txt for license information.
  6. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  7. //
  8. //===----------------------------------------------------------------------===//
  9. // UNSUPPORTED: c++98, c++03, c++11, c++14
  10. // <variant>
  11. // template <class ...Types>
  12. // constexpr bool
  13. // operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
  14. //
  15. // template <class ...Types>
  16. // constexpr bool
  17. // operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
  18. //
  19. // template <class ...Types>
  20. // constexpr bool
  21. // operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
  22. //
  23. // template <class ...Types>
  24. // constexpr bool
  25. // operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
  26. //
  27. // template <class ...Types>
  28. // constexpr bool
  29. // operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
  30. //
  31. // template <class ...Types>
  32. // constexpr bool
  33. // operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
  34. #include <cassert>
  35. #include <type_traits>
  36. #include <utility>
  37. #include <variant>
  38. #include "test_macros.h"
  39. #ifndef TEST_HAS_NO_EXCEPTIONS
  40. struct MakeEmptyT {
  41. MakeEmptyT() = default;
  42. MakeEmptyT(MakeEmptyT &&) { throw 42; }
  43. MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
  44. };
  45. inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
  46. assert(false);
  47. return false;
  48. }
  49. inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
  50. assert(false);
  51. return false;
  52. }
  53. inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
  54. assert(false);
  55. return false;
  56. }
  57. inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
  58. assert(false);
  59. return false;
  60. }
  61. inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
  62. assert(false);
  63. return false;
  64. }
  65. inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
  66. assert(false);
  67. return false;
  68. }
  69. template <class Variant> void makeEmpty(Variant &v) {
  70. Variant v2(std::in_place_type<MakeEmptyT>);
  71. try {
  72. v = std::move(v2);
  73. assert(false);
  74. } catch (...) {
  75. assert(v.valueless_by_exception());
  76. }
  77. }
  78. #endif // TEST_HAS_NO_EXCEPTIONS
  79. struct MyBool {
  80. bool value;
  81. constexpr explicit MyBool(bool v) : value(v) {}
  82. constexpr operator bool() const noexcept { return value; }
  83. };
  84. struct ComparesToMyBool {
  85. int value = 0;
  86. };
  87. inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  88. return MyBool(LHS.value == RHS.value);
  89. }
  90. inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  91. return MyBool(LHS.value != RHS.value);
  92. }
  93. inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  94. return MyBool(LHS.value < RHS.value);
  95. }
  96. inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  97. return MyBool(LHS.value <= RHS.value);
  98. }
  99. inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  100. return MyBool(LHS.value > RHS.value);
  101. }
  102. inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
  103. return MyBool(LHS.value >= RHS.value);
  104. }
  105. template <class T1, class T2>
  106. void test_equality_basic() {
  107. {
  108. using V = std::variant<T1, T2>;
  109. constexpr V v1(std::in_place_index<0>, T1{42});
  110. constexpr V v2(std::in_place_index<0>, T1{42});
  111. static_assert(v1 == v2, "");
  112. static_assert(v2 == v1, "");
  113. static_assert(!(v1 != v2), "");
  114. static_assert(!(v2 != v1), "");
  115. }
  116. {
  117. using V = std::variant<T1, T2>;
  118. constexpr V v1(std::in_place_index<0>, T1{42});
  119. constexpr V v2(std::in_place_index<0>, T1{43});
  120. static_assert(!(v1 == v2), "");
  121. static_assert(!(v2 == v1), "");
  122. static_assert(v1 != v2, "");
  123. static_assert(v2 != v1, "");
  124. }
  125. {
  126. using V = std::variant<T1, T2>;
  127. constexpr V v1(std::in_place_index<0>, T1{42});
  128. constexpr V v2(std::in_place_index<1>, T2{42});
  129. static_assert(!(v1 == v2), "");
  130. static_assert(!(v2 == v1), "");
  131. static_assert(v1 != v2, "");
  132. static_assert(v2 != v1, "");
  133. }
  134. {
  135. using V = std::variant<T1, T2>;
  136. constexpr V v1(std::in_place_index<1>, T2{42});
  137. constexpr V v2(std::in_place_index<1>, T2{42});
  138. static_assert(v1 == v2, "");
  139. static_assert(v2 == v1, "");
  140. static_assert(!(v1 != v2), "");
  141. static_assert(!(v2 != v1), "");
  142. }
  143. }
  144. void test_equality() {
  145. test_equality_basic<int, long>();
  146. test_equality_basic<ComparesToMyBool, int>();
  147. test_equality_basic<int, ComparesToMyBool>();
  148. test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
  149. #ifndef TEST_HAS_NO_EXCEPTIONS
  150. {
  151. using V = std::variant<int, MakeEmptyT>;
  152. V v1;
  153. V v2;
  154. makeEmpty(v2);
  155. assert(!(v1 == v2));
  156. assert(!(v2 == v1));
  157. assert(v1 != v2);
  158. assert(v2 != v1);
  159. }
  160. {
  161. using V = std::variant<int, MakeEmptyT>;
  162. V v1;
  163. makeEmpty(v1);
  164. V v2;
  165. assert(!(v1 == v2));
  166. assert(!(v2 == v1));
  167. assert(v1 != v2);
  168. assert(v2 != v1);
  169. }
  170. {
  171. using V = std::variant<int, MakeEmptyT>;
  172. V v1;
  173. makeEmpty(v1);
  174. V v2;
  175. makeEmpty(v2);
  176. assert(v1 == v2);
  177. assert(v2 == v1);
  178. assert(!(v1 != v2));
  179. assert(!(v2 != v1));
  180. }
  181. #endif
  182. }
  183. template <class Var>
  184. constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
  185. bool expect_greater) {
  186. static_assert(std::is_same_v<decltype(l < r), bool>, "");
  187. static_assert(std::is_same_v<decltype(l <= r), bool>, "");
  188. static_assert(std::is_same_v<decltype(l > r), bool>, "");
  189. static_assert(std::is_same_v<decltype(l >= r), bool>, "");
  190. return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
  191. ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
  192. }
  193. template <class T1, class T2>
  194. void test_relational_basic() {
  195. { // same index, same value
  196. using V = std::variant<T1, T2>;
  197. constexpr V v1(std::in_place_index<0>, T1{1});
  198. constexpr V v2(std::in_place_index<0>, T1{1});
  199. static_assert(test_less(v1, v2, false, false), "");
  200. }
  201. { // same index, value < other_value
  202. using V = std::variant<T1, T2>;
  203. constexpr V v1(std::in_place_index<0>, T1{0});
  204. constexpr V v2(std::in_place_index<0>, T1{1});
  205. static_assert(test_less(v1, v2, true, false), "");
  206. }
  207. { // same index, value > other_value
  208. using V = std::variant<T1, T2>;
  209. constexpr V v1(std::in_place_index<0>, T1{1});
  210. constexpr V v2(std::in_place_index<0>, T1{0});
  211. static_assert(test_less(v1, v2, false, true), "");
  212. }
  213. { // LHS.index() < RHS.index()
  214. using V = std::variant<T1, T2>;
  215. constexpr V v1(std::in_place_index<0>, T1{0});
  216. constexpr V v2(std::in_place_index<1>, T2{0});
  217. static_assert(test_less(v1, v2, true, false), "");
  218. }
  219. { // LHS.index() > RHS.index()
  220. using V = std::variant<T1, T2>;
  221. constexpr V v1(std::in_place_index<1>, T2{0});
  222. constexpr V v2(std::in_place_index<0>, T1{0});
  223. static_assert(test_less(v1, v2, false, true), "");
  224. }
  225. }
  226. void test_relational() {
  227. test_relational_basic<int, long>();
  228. test_relational_basic<ComparesToMyBool, int>();
  229. test_relational_basic<int, ComparesToMyBool>();
  230. test_relational_basic<ComparesToMyBool, ComparesToMyBool>();
  231. #ifndef TEST_HAS_NO_EXCEPTIONS
  232. { // LHS.index() < RHS.index(), RHS is empty
  233. using V = std::variant<int, MakeEmptyT>;
  234. V v1;
  235. V v2;
  236. makeEmpty(v2);
  237. assert(test_less(v1, v2, false, true));
  238. }
  239. { // LHS.index() > RHS.index(), LHS is empty
  240. using V = std::variant<int, MakeEmptyT>;
  241. V v1;
  242. makeEmpty(v1);
  243. V v2;
  244. assert(test_less(v1, v2, true, false));
  245. }
  246. { // LHS.index() == RHS.index(), LHS and RHS are empty
  247. using V = std::variant<int, MakeEmptyT>;
  248. V v1;
  249. makeEmpty(v1);
  250. V v2;
  251. makeEmpty(v2);
  252. assert(test_less(v1, v2, false, false));
  253. }
  254. #endif
  255. }
  256. int main(int, char**) {
  257. test_equality();
  258. test_relational();
  259. return 0;
  260. }