180e66ac1SEric Fiselier //===----------------------------------------------------------------------===//
280e66ac1SEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
680e66ac1SEric Fiselier //
780e66ac1SEric Fiselier //===----------------------------------------------------------------------===//
880e66ac1SEric Fiselier
9*31cbe0f2SLouis Dionne // UNSUPPORTED: c++03, c++11, c++14
1080e66ac1SEric Fiselier
1180e66ac1SEric Fiselier // <variant>
1280e66ac1SEric Fiselier
1380e66ac1SEric Fiselier // template <class ...Types>
1480e66ac1SEric Fiselier // constexpr bool
1580e66ac1SEric Fiselier // operator==(variant<Types...> const&, variant<Types...> const&) noexcept;
1680e66ac1SEric Fiselier //
1780e66ac1SEric Fiselier // template <class ...Types>
1880e66ac1SEric Fiselier // constexpr bool
1980e66ac1SEric Fiselier // operator!=(variant<Types...> const&, variant<Types...> const&) noexcept;
2080e66ac1SEric Fiselier //
2180e66ac1SEric Fiselier // template <class ...Types>
2280e66ac1SEric Fiselier // constexpr bool
2380e66ac1SEric Fiselier // operator<(variant<Types...> const&, variant<Types...> const&) noexcept;
2480e66ac1SEric Fiselier //
2580e66ac1SEric Fiselier // template <class ...Types>
2680e66ac1SEric Fiselier // constexpr bool
2780e66ac1SEric Fiselier // operator>(variant<Types...> const&, variant<Types...> const&) noexcept;
2880e66ac1SEric Fiselier //
2980e66ac1SEric Fiselier // template <class ...Types>
3080e66ac1SEric Fiselier // constexpr bool
3180e66ac1SEric Fiselier // operator<=(variant<Types...> const&, variant<Types...> const&) noexcept;
3280e66ac1SEric Fiselier //
3380e66ac1SEric Fiselier // template <class ...Types>
3480e66ac1SEric Fiselier // constexpr bool
3580e66ac1SEric Fiselier // operator>=(variant<Types...> const&, variant<Types...> const&) noexcept;
3680e66ac1SEric Fiselier
3780e66ac1SEric Fiselier #include <cassert>
3880e66ac1SEric Fiselier #include <type_traits>
3980e66ac1SEric Fiselier #include <utility>
4080e66ac1SEric Fiselier #include <variant>
4180e66ac1SEric Fiselier
4280e66ac1SEric Fiselier #include "test_macros.h"
4380e66ac1SEric Fiselier
4480e66ac1SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
4580e66ac1SEric Fiselier struct MakeEmptyT {
4680e66ac1SEric Fiselier MakeEmptyT() = default;
MakeEmptyTMakeEmptyT4780e66ac1SEric Fiselier MakeEmptyT(MakeEmptyT &&) { throw 42; }
operator =MakeEmptyT4880e66ac1SEric Fiselier MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
4980e66ac1SEric Fiselier };
operator ==(const MakeEmptyT &,const MakeEmptyT &)500d3d8de0SEric Fiselier inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
5180e66ac1SEric Fiselier assert(false);
5280e66ac1SEric Fiselier return false;
5380e66ac1SEric Fiselier }
operator !=(const MakeEmptyT &,const MakeEmptyT &)540d3d8de0SEric Fiselier inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
5580e66ac1SEric Fiselier assert(false);
5680e66ac1SEric Fiselier return false;
5780e66ac1SEric Fiselier }
operator <(const MakeEmptyT &,const MakeEmptyT &)580d3d8de0SEric Fiselier inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
5980e66ac1SEric Fiselier assert(false);
6080e66ac1SEric Fiselier return false;
6180e66ac1SEric Fiselier }
operator <=(const MakeEmptyT &,const MakeEmptyT &)620d3d8de0SEric Fiselier inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
6380e66ac1SEric Fiselier assert(false);
6480e66ac1SEric Fiselier return false;
6580e66ac1SEric Fiselier }
operator >(const MakeEmptyT &,const MakeEmptyT &)660d3d8de0SEric Fiselier inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
6780e66ac1SEric Fiselier assert(false);
6880e66ac1SEric Fiselier return false;
6980e66ac1SEric Fiselier }
operator >=(const MakeEmptyT &,const MakeEmptyT &)700d3d8de0SEric Fiselier inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
7180e66ac1SEric Fiselier assert(false);
7280e66ac1SEric Fiselier return false;
7380e66ac1SEric Fiselier }
7480e66ac1SEric Fiselier
makeEmpty(Variant & v)7580e66ac1SEric Fiselier template <class Variant> void makeEmpty(Variant &v) {
7680e66ac1SEric Fiselier Variant v2(std::in_place_type<MakeEmptyT>);
7780e66ac1SEric Fiselier try {
7880e66ac1SEric Fiselier v = std::move(v2);
7980e66ac1SEric Fiselier assert(false);
8080e66ac1SEric Fiselier } catch (...) {
8180e66ac1SEric Fiselier assert(v.valueless_by_exception());
8280e66ac1SEric Fiselier }
8380e66ac1SEric Fiselier }
8480e66ac1SEric Fiselier #endif // TEST_HAS_NO_EXCEPTIONS
8580e66ac1SEric Fiselier
867dca3127SEric Fiselier struct MyBool {
877dca3127SEric Fiselier bool value;
MyBoolMyBool887dca3127SEric Fiselier constexpr explicit MyBool(bool v) : value(v) {}
operator boolMyBool897dca3127SEric Fiselier constexpr operator bool() const noexcept { return value; }
907dca3127SEric Fiselier };
917dca3127SEric Fiselier
927dca3127SEric Fiselier struct ComparesToMyBool {
937dca3127SEric Fiselier int value = 0;
947dca3127SEric Fiselier };
operator ==(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)957dca3127SEric Fiselier inline constexpr MyBool operator==(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
967dca3127SEric Fiselier return MyBool(LHS.value == RHS.value);
977dca3127SEric Fiselier }
operator !=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)987dca3127SEric Fiselier inline constexpr MyBool operator!=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
997dca3127SEric Fiselier return MyBool(LHS.value != RHS.value);
1007dca3127SEric Fiselier }
operator <(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)1017dca3127SEric Fiselier inline constexpr MyBool operator<(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
1027dca3127SEric Fiselier return MyBool(LHS.value < RHS.value);
1037dca3127SEric Fiselier }
operator <=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)1047dca3127SEric Fiselier inline constexpr MyBool operator<=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
1057dca3127SEric Fiselier return MyBool(LHS.value <= RHS.value);
1067dca3127SEric Fiselier }
operator >(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)1077dca3127SEric Fiselier inline constexpr MyBool operator>(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
1087dca3127SEric Fiselier return MyBool(LHS.value > RHS.value);
1097dca3127SEric Fiselier }
operator >=(const ComparesToMyBool & LHS,const ComparesToMyBool & RHS)1107dca3127SEric Fiselier inline constexpr MyBool operator>=(const ComparesToMyBool& LHS, const ComparesToMyBool& RHS) noexcept {
1117dca3127SEric Fiselier return MyBool(LHS.value >= RHS.value);
1127dca3127SEric Fiselier }
1137dca3127SEric Fiselier
1147dca3127SEric Fiselier template <class T1, class T2>
test_equality_basic()1157dca3127SEric Fiselier void test_equality_basic() {
1167dca3127SEric Fiselier {
1177dca3127SEric Fiselier using V = std::variant<T1, T2>;
1187dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{42});
1197dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{42});
1207dca3127SEric Fiselier static_assert(v1 == v2, "");
1217dca3127SEric Fiselier static_assert(v2 == v1, "");
1227dca3127SEric Fiselier static_assert(!(v1 != v2), "");
1237dca3127SEric Fiselier static_assert(!(v2 != v1), "");
1247dca3127SEric Fiselier }
1257dca3127SEric Fiselier {
1267dca3127SEric Fiselier using V = std::variant<T1, T2>;
1277dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{42});
1287dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{43});
1297dca3127SEric Fiselier static_assert(!(v1 == v2), "");
1307dca3127SEric Fiselier static_assert(!(v2 == v1), "");
1317dca3127SEric Fiselier static_assert(v1 != v2, "");
1327dca3127SEric Fiselier static_assert(v2 != v1, "");
1337dca3127SEric Fiselier }
1347dca3127SEric Fiselier {
1357dca3127SEric Fiselier using V = std::variant<T1, T2>;
1367dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{42});
1377dca3127SEric Fiselier constexpr V v2(std::in_place_index<1>, T2{42});
1387dca3127SEric Fiselier static_assert(!(v1 == v2), "");
1397dca3127SEric Fiselier static_assert(!(v2 == v1), "");
1407dca3127SEric Fiselier static_assert(v1 != v2, "");
1417dca3127SEric Fiselier static_assert(v2 != v1, "");
1427dca3127SEric Fiselier }
1437dca3127SEric Fiselier {
1447dca3127SEric Fiselier using V = std::variant<T1, T2>;
1457dca3127SEric Fiselier constexpr V v1(std::in_place_index<1>, T2{42});
1467dca3127SEric Fiselier constexpr V v2(std::in_place_index<1>, T2{42});
1477dca3127SEric Fiselier static_assert(v1 == v2, "");
1487dca3127SEric Fiselier static_assert(v2 == v1, "");
1497dca3127SEric Fiselier static_assert(!(v1 != v2), "");
1507dca3127SEric Fiselier static_assert(!(v2 != v1), "");
1517dca3127SEric Fiselier }
1527dca3127SEric Fiselier }
1537dca3127SEric Fiselier
test_equality()15480e66ac1SEric Fiselier void test_equality() {
1557dca3127SEric Fiselier test_equality_basic<int, long>();
1567dca3127SEric Fiselier test_equality_basic<ComparesToMyBool, int>();
1577dca3127SEric Fiselier test_equality_basic<int, ComparesToMyBool>();
1587dca3127SEric Fiselier test_equality_basic<ComparesToMyBool, ComparesToMyBool>();
15980e66ac1SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
16080e66ac1SEric Fiselier {
16180e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
16280e66ac1SEric Fiselier V v1;
16380e66ac1SEric Fiselier V v2;
16480e66ac1SEric Fiselier makeEmpty(v2);
16580e66ac1SEric Fiselier assert(!(v1 == v2));
16680e66ac1SEric Fiselier assert(!(v2 == v1));
16780e66ac1SEric Fiselier assert(v1 != v2);
16880e66ac1SEric Fiselier assert(v2 != v1);
16980e66ac1SEric Fiselier }
17080e66ac1SEric Fiselier {
17180e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
17280e66ac1SEric Fiselier V v1;
17380e66ac1SEric Fiselier makeEmpty(v1);
17480e66ac1SEric Fiselier V v2;
17580e66ac1SEric Fiselier assert(!(v1 == v2));
17680e66ac1SEric Fiselier assert(!(v2 == v1));
17780e66ac1SEric Fiselier assert(v1 != v2);
17880e66ac1SEric Fiselier assert(v2 != v1);
17980e66ac1SEric Fiselier }
18080e66ac1SEric Fiselier {
18180e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
18280e66ac1SEric Fiselier V v1;
18380e66ac1SEric Fiselier makeEmpty(v1);
18480e66ac1SEric Fiselier V v2;
18580e66ac1SEric Fiselier makeEmpty(v2);
18680e66ac1SEric Fiselier assert(v1 == v2);
18780e66ac1SEric Fiselier assert(v2 == v1);
18880e66ac1SEric Fiselier assert(!(v1 != v2));
18980e66ac1SEric Fiselier assert(!(v2 != v1));
19080e66ac1SEric Fiselier }
19180e66ac1SEric Fiselier #endif
19280e66ac1SEric Fiselier }
19380e66ac1SEric Fiselier
19480e66ac1SEric Fiselier template <class Var>
test_less(const Var & l,const Var & r,bool expect_less,bool expect_greater)1950d3d8de0SEric Fiselier constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
19680e66ac1SEric Fiselier bool expect_greater) {
1977dca3127SEric Fiselier static_assert(std::is_same_v<decltype(l < r), bool>, "");
1987dca3127SEric Fiselier static_assert(std::is_same_v<decltype(l <= r), bool>, "");
1997dca3127SEric Fiselier static_assert(std::is_same_v<decltype(l > r), bool>, "");
2007dca3127SEric Fiselier static_assert(std::is_same_v<decltype(l >= r), bool>, "");
2017dca3127SEric Fiselier
20280e66ac1SEric Fiselier return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
20380e66ac1SEric Fiselier ((l > r) == expect_greater) && (!(l <= r) == expect_greater);
20480e66ac1SEric Fiselier }
20580e66ac1SEric Fiselier
2067dca3127SEric Fiselier template <class T1, class T2>
test_relational_basic()2077dca3127SEric Fiselier void test_relational_basic() {
20880e66ac1SEric Fiselier { // same index, same value
2097dca3127SEric Fiselier using V = std::variant<T1, T2>;
2107dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{1});
2117dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{1});
21280e66ac1SEric Fiselier static_assert(test_less(v1, v2, false, false), "");
21380e66ac1SEric Fiselier }
21480e66ac1SEric Fiselier { // same index, value < other_value
2157dca3127SEric Fiselier using V = std::variant<T1, T2>;
2167dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{0});
2177dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{1});
21880e66ac1SEric Fiselier static_assert(test_less(v1, v2, true, false), "");
21980e66ac1SEric Fiselier }
22080e66ac1SEric Fiselier { // same index, value > other_value
2217dca3127SEric Fiselier using V = std::variant<T1, T2>;
2227dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{1});
2237dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{0});
22480e66ac1SEric Fiselier static_assert(test_less(v1, v2, false, true), "");
22580e66ac1SEric Fiselier }
22680e66ac1SEric Fiselier { // LHS.index() < RHS.index()
2277dca3127SEric Fiselier using V = std::variant<T1, T2>;
2287dca3127SEric Fiselier constexpr V v1(std::in_place_index<0>, T1{0});
2297dca3127SEric Fiselier constexpr V v2(std::in_place_index<1>, T2{0});
23080e66ac1SEric Fiselier static_assert(test_less(v1, v2, true, false), "");
23180e66ac1SEric Fiselier }
23280e66ac1SEric Fiselier { // LHS.index() > RHS.index()
2337dca3127SEric Fiselier using V = std::variant<T1, T2>;
2347dca3127SEric Fiselier constexpr V v1(std::in_place_index<1>, T2{0});
2357dca3127SEric Fiselier constexpr V v2(std::in_place_index<0>, T1{0});
23680e66ac1SEric Fiselier static_assert(test_less(v1, v2, false, true), "");
23780e66ac1SEric Fiselier }
2387dca3127SEric Fiselier }
2397dca3127SEric Fiselier
test_relational()2407dca3127SEric Fiselier void test_relational() {
2417dca3127SEric Fiselier test_relational_basic<int, long>();
2427dca3127SEric Fiselier test_relational_basic<ComparesToMyBool, int>();
2437dca3127SEric Fiselier test_relational_basic<int, ComparesToMyBool>();
2447dca3127SEric Fiselier test_relational_basic<ComparesToMyBool, ComparesToMyBool>();
24580e66ac1SEric Fiselier #ifndef TEST_HAS_NO_EXCEPTIONS
24680e66ac1SEric Fiselier { // LHS.index() < RHS.index(), RHS is empty
24780e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
24880e66ac1SEric Fiselier V v1;
24980e66ac1SEric Fiselier V v2;
25080e66ac1SEric Fiselier makeEmpty(v2);
25180e66ac1SEric Fiselier assert(test_less(v1, v2, false, true));
25280e66ac1SEric Fiselier }
25380e66ac1SEric Fiselier { // LHS.index() > RHS.index(), LHS is empty
25480e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
25580e66ac1SEric Fiselier V v1;
25680e66ac1SEric Fiselier makeEmpty(v1);
25780e66ac1SEric Fiselier V v2;
25880e66ac1SEric Fiselier assert(test_less(v1, v2, true, false));
25980e66ac1SEric Fiselier }
26080e66ac1SEric Fiselier { // LHS.index() == RHS.index(), LHS and RHS are empty
26180e66ac1SEric Fiselier using V = std::variant<int, MakeEmptyT>;
26280e66ac1SEric Fiselier V v1;
26380e66ac1SEric Fiselier makeEmpty(v1);
26480e66ac1SEric Fiselier V v2;
26580e66ac1SEric Fiselier makeEmpty(v2);
26680e66ac1SEric Fiselier assert(test_less(v1, v2, false, false));
26780e66ac1SEric Fiselier }
26880e66ac1SEric Fiselier #endif
26980e66ac1SEric Fiselier }
27080e66ac1SEric Fiselier
main(int,char **)2712df59c50SJF Bastien int main(int, char**) {
27280e66ac1SEric Fiselier test_equality();
27380e66ac1SEric Fiselier test_relational();
2742df59c50SJF Bastien
2752df59c50SJF Bastien return 0;
27680e66ac1SEric Fiselier }
277