1// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
4//                     The LLVM Compiler Infrastructure
5//
6// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11// UNSUPPORTED: c++98, c++03, c++11, c++14
12
13// <variant>
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//
35// template <class ...Types>
36// constexpr bool
37// operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
38
39#include <cassert>
40#include <type_traits>
41#include <utility>
42#include <variant>
43
44#include "test_macros.h"
45
46#ifndef TEST_HAS_NO_EXCEPTIONS
47struct MakeEmptyT {
48  MakeEmptyT() = default;
49  MakeEmptyT(MakeEmptyT &&) { throw 42; }
50  MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
51};
52inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
53  assert(false);
54  return false;
55}
56inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
57  assert(false);
58  return false;
59}
60inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
61  assert(false);
62  return false;
63}
64inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
65  assert(false);
66  return false;
67}
68inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
69  assert(false);
70  return false;
71}
72inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
73  assert(false);
74  return false;
75}
76
77template <class Variant> void makeEmpty(Variant &v) {
78  Variant v2(std::in_place_type<MakeEmptyT>);
79  try {
80    v = std::move(v2);
81    assert(false);
82  } catch (...) {
83    assert(v.valueless_by_exception());
84  }
85}
86#endif // TEST_HAS_NO_EXCEPTIONS
87
88void test_equality() {
89  {
90    using V = std::variant<int, long>;
91    constexpr V v1(42);
92    constexpr V v2(42);
93    static_assert(v1 == v2, "");
94    static_assert(v2 == v1, "");
95    static_assert(!(v1 != v2), "");
96    static_assert(!(v2 != v1), "");
97  }
98  {
99    using V = std::variant<int, long>;
100    constexpr V v1(42);
101    constexpr V v2(43);
102    static_assert(!(v1 == v2), "");
103    static_assert(!(v2 == v1), "");
104    static_assert(v1 != v2, "");
105    static_assert(v2 != v1, "");
106  }
107  {
108    using V = std::variant<int, long>;
109    constexpr V v1(42);
110    constexpr V v2(42l);
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<int, long>;
118    constexpr V v1(42l);
119    constexpr V v2(42l);
120    static_assert(v1 == v2, "");
121    static_assert(v2 == v1, "");
122    static_assert(!(v1 != v2), "");
123    static_assert(!(v2 != v1), "");
124  }
125#ifndef TEST_HAS_NO_EXCEPTIONS
126  {
127    using V = std::variant<int, MakeEmptyT>;
128    V v1;
129    V v2;
130    makeEmpty(v2);
131    assert(!(v1 == v2));
132    assert(!(v2 == v1));
133    assert(v1 != v2);
134    assert(v2 != v1);
135  }
136  {
137    using V = std::variant<int, MakeEmptyT>;
138    V v1;
139    makeEmpty(v1);
140    V v2;
141    assert(!(v1 == v2));
142    assert(!(v2 == v1));
143    assert(v1 != v2);
144    assert(v2 != v1);
145  }
146  {
147    using V = std::variant<int, MakeEmptyT>;
148    V v1;
149    makeEmpty(v1);
150    V v2;
151    makeEmpty(v2);
152    assert(v1 == v2);
153    assert(v2 == v1);
154    assert(!(v1 != v2));
155    assert(!(v2 != v1));
156  }
157#endif
158}
159
160template <class Var>
161constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
162                         bool expect_greater) {
163  return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
164         ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
165}
166
167void test_relational() {
168  { // same index, same value
169    using V = std::variant<int, long>;
170    constexpr V v1(1);
171    constexpr V v2(1);
172    static_assert(test_less(v1, v2, false, false), "");
173  }
174  { // same index, value < other_value
175    using V = std::variant<int, long>;
176    constexpr V v1(0);
177    constexpr V v2(1);
178    static_assert(test_less(v1, v2, true, false), "");
179  }
180  { // same index, value > other_value
181    using V = std::variant<int, long>;
182    constexpr V v1(1);
183    constexpr V v2(0);
184    static_assert(test_less(v1, v2, false, true), "");
185  }
186  { // LHS.index() < RHS.index()
187    using V = std::variant<int, long>;
188    constexpr V v1(0);
189    constexpr V v2(0l);
190    static_assert(test_less(v1, v2, true, false), "");
191  }
192  { // LHS.index() > RHS.index()
193    using V = std::variant<int, long>;
194    constexpr V v1(0l);
195    constexpr V v2(0);
196    static_assert(test_less(v1, v2, false, true), "");
197  }
198#ifndef TEST_HAS_NO_EXCEPTIONS
199  { // LHS.index() < RHS.index(), RHS is empty
200    using V = std::variant<int, MakeEmptyT>;
201    V v1;
202    V v2;
203    makeEmpty(v2);
204    assert(test_less(v1, v2, false, true));
205  }
206  { // LHS.index() > RHS.index(), LHS is empty
207    using V = std::variant<int, MakeEmptyT>;
208    V v1;
209    makeEmpty(v1);
210    V v2;
211    assert(test_less(v1, v2, true, false));
212  }
213  { // LHS.index() == RHS.index(), LHS and RHS are empty
214    using V = std::variant<int, MakeEmptyT>;
215    V v1;
216    makeEmpty(v1);
217    V v2;
218    makeEmpty(v2);
219    assert(test_less(v1, v2, false, false));
220  }
221#endif
222}
223
224int main() {
225  test_equality();
226  test_relational();
227}
228