brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · c235967 Raw
195 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++1710 11// <variant>12 13// template <class... Types> class variant;14 15// template <class... Types> requires (three_way_comparable<Types> && ...)16//   constexpr std::common_comparison_category_t<17//     std::compare_three_way_result_t<Types>...>18//   operator<=>(const variant<Types...>& t, const variant<Types...>& u);19 20#include <cassert>21#include <limits>22#include <type_traits>23#include <utility>24#include <variant>25 26#include "test_macros.h"27#include "test_comparisons.h"28 29#ifndef TEST_HAS_NO_EXCEPTIONS30// MakeEmptyT throws in operator=(&&), so we can move to it to create valueless-by-exception variants.31struct MakeEmptyT {32  MakeEmptyT() = default;33  MakeEmptyT(MakeEmptyT&&) { throw 42; }34  MakeEmptyT& operator=(MakeEmptyT&&) { throw 42; }35};36inline bool operator==(const MakeEmptyT&, const MakeEmptyT&) {37  assert(false);38  return false;39}40inline std::weak_ordering operator<=>(const MakeEmptyT&, const MakeEmptyT&) {41  assert(false);42  return std::weak_ordering::equivalent;43}44 45template <class Variant>46void makeEmpty(Variant& v) {47  Variant v2(std::in_place_type<MakeEmptyT>);48  try {49    v = std::move(v2);50    assert(false);51  } catch (...) {52    assert(v.valueless_by_exception());53  }54}55 56void test_empty() {57  {58    using V = std::variant<int, MakeEmptyT>;59    V v1;60    V v2;61    makeEmpty(v2);62    assert(testOrder(v1, v2, std::weak_ordering::greater));63  }64  {65    using V = std::variant<int, MakeEmptyT>;66    V v1;67    makeEmpty(v1);68    V v2;69    assert(testOrder(v1, v2, std::weak_ordering::less));70  }71  {72    using V = std::variant<int, MakeEmptyT>;73    V v1;74    makeEmpty(v1);75    V v2;76    makeEmpty(v2);77    assert(testOrder(v1, v2, std::weak_ordering::equivalent));78  }79}80#endif // TEST_HAS_NO_EXCEPTIONS81 82template <class T1, class T2, class Order>83constexpr bool test_with_types() {84  using V = std::variant<T1, T2>;85  AssertOrderReturn<Order, V>();86  { // same index, same value87    constexpr V v1(std::in_place_index<0>, T1{1});88    constexpr V v2(std::in_place_index<0>, T1{1});89    assert(testOrder(v1, v2, Order::equivalent));90  }91  { // same index, value < other_value92    constexpr V v1(std::in_place_index<0>, T1{0});93    constexpr V v2(std::in_place_index<0>, T1{1});94    assert(testOrder(v1, v2, Order::less));95  }96  { // same index, value > other_value97    constexpr V v1(std::in_place_index<0>, T1{1});98    constexpr V v2(std::in_place_index<0>, T1{0});99    assert(testOrder(v1, v2, Order::greater));100  }101  { // LHS.index() < RHS.index()102    constexpr V v1(std::in_place_index<0>, T1{0});103    constexpr V v2(std::in_place_index<1>, T2{0});104    assert(testOrder(v1, v2, Order::less));105  }106  { // LHS.index() > RHS.index()107    constexpr V v1(std::in_place_index<1>, T2{0});108    constexpr V v2(std::in_place_index<0>, T1{0});109    assert(testOrder(v1, v2, Order::greater));110  }111 112  return true;113}114 115constexpr bool test_three_way() {116  assert((test_with_types<int, double, std::partial_ordering>()));117  assert((test_with_types<int, long, std::strong_ordering>()));118 119  {120    using V              = std::variant<int, double>;121    constexpr double nan = std::numeric_limits<double>::quiet_NaN();122    {123      constexpr V v1(std::in_place_type<int>, 1);124      constexpr V v2(std::in_place_type<double>, nan);125      assert(testOrder(v1, v2, std::partial_ordering::less));126    }127    {128      constexpr V v1(std::in_place_type<double>, nan);129      constexpr V v2(std::in_place_type<int>, 2);130      assert(testOrder(v1, v2, std::partial_ordering::greater));131    }132    {133      constexpr V v1(std::in_place_type<double>, nan);134      constexpr V v2(std::in_place_type<double>, nan);135      assert(testOrder(v1, v2, std::partial_ordering::unordered));136    }137  }138 139  return true;140}141 142// SFINAE tests143template <class T, class U = T>144concept has_three_way_op = requires (T& t, U& u) { t <=> u; };145 146// std::three_way_comparable is a more stringent requirement that demands147// operator== and a few other things.148using std::three_way_comparable;149 150struct HasSimpleOrdering {151  constexpr bool operator==(const HasSimpleOrdering&) const;152  constexpr bool operator<(const HasSimpleOrdering&) const;153};154 155struct HasOnlySpaceship {156  constexpr bool operator==(const HasOnlySpaceship&) const = delete;157  constexpr std::weak_ordering operator<=>(const HasOnlySpaceship&) const;158};159 160struct HasFullOrdering {161  constexpr bool operator==(const HasFullOrdering&) const;162  constexpr std::weak_ordering operator<=>(const HasFullOrdering&) const;163};164 165// operator<=> must resolve the return types of all its union types'166// operator<=>s to determine its own return type, so it is detectable by SFINAE167static_assert(!has_three_way_op<HasSimpleOrdering>);168static_assert(!has_three_way_op<std::variant<int, HasSimpleOrdering>>);169 170static_assert(!three_way_comparable<HasSimpleOrdering>);171static_assert(!three_way_comparable<std::variant<int, HasSimpleOrdering>>);172 173static_assert(has_three_way_op<HasOnlySpaceship>);174static_assert(!has_three_way_op<std::variant<int, HasOnlySpaceship>>);175 176static_assert(!three_way_comparable<HasOnlySpaceship>);177static_assert(!three_way_comparable<std::variant<int, HasOnlySpaceship>>);178 179static_assert( has_three_way_op<HasFullOrdering>);180static_assert( has_three_way_op<std::variant<int, HasFullOrdering>>);181 182static_assert( three_way_comparable<HasFullOrdering>);183static_assert( three_way_comparable<std::variant<int, HasFullOrdering>>);184 185int main(int, char**) {186  test_three_way();187  static_assert(test_three_way());188 189#ifndef TEST_HAS_NO_EXCEPTIONS190  test_empty();191#endif // TEST_HAS_NO_EXCEPTIONS192 193  return 0;194}195