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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef SORTABLE_HELPERS_H 10 #define SORTABLE_HELPERS_H 11 12 #include <type_traits> 13 14 #include "test_macros.h" 15 16 #if TEST_STD_VER > 17 17 #include <compare> 18 #include <iterator> 19 #include "test_iterators.h" 20 #endif 21 22 struct TrivialSortable { 23 int value; TrivialSortableTrivialSortable24 TEST_CONSTEXPR TrivialSortable() : value(0) {} TrivialSortableTrivialSortable25 TEST_CONSTEXPR TrivialSortable(int v) : value(v) {} 26 friend TEST_CONSTEXPR bool operator<(const TrivialSortable& a, const TrivialSortable& b) { 27 return a.value / 10 < b.value / 10; 28 } lessTrivialSortable29 static TEST_CONSTEXPR bool less(const TrivialSortable& a, const TrivialSortable& b) { 30 return a.value < b.value; 31 } 32 }; 33 34 struct NonTrivialSortable { 35 int value; NonTrivialSortableNonTrivialSortable36 TEST_CONSTEXPR NonTrivialSortable() : value(0) {} NonTrivialSortableNonTrivialSortable37 TEST_CONSTEXPR NonTrivialSortable(int v) : value(v) {} NonTrivialSortableNonTrivialSortable38 TEST_CONSTEXPR NonTrivialSortable(const NonTrivialSortable& rhs) : value(rhs.value) {} 39 TEST_CONSTEXPR_CXX14 NonTrivialSortable& operator=(const NonTrivialSortable& rhs) { value = rhs.value; return *this; } 40 friend TEST_CONSTEXPR bool operator<(const NonTrivialSortable& a, const NonTrivialSortable& b) { 41 return a.value / 10 < b.value / 10; 42 } lessNonTrivialSortable43 static TEST_CONSTEXPR bool less(const NonTrivialSortable& a, const NonTrivialSortable& b) { 44 return a.value < b.value; 45 } 46 }; 47 48 49 struct TrivialSortableWithComp { 50 int value; TrivialSortableWithCompTrivialSortableWithComp51 TEST_CONSTEXPR TrivialSortableWithComp() : value(0) {} TrivialSortableWithCompTrivialSortableWithComp52 TEST_CONSTEXPR TrivialSortableWithComp(int v) : value(v) {} 53 struct Comparator { operatorTrivialSortableWithComp::Comparator54 TEST_CONSTEXPR bool operator()(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) const { 55 return a.value / 10 < b.value / 10; 56 } 57 }; lessTrivialSortableWithComp58 static TEST_CONSTEXPR bool less(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) { 59 return a.value < b.value; 60 } 61 }; 62 63 struct NonTrivialSortableWithComp { 64 int value; NonTrivialSortableWithCompNonTrivialSortableWithComp65 TEST_CONSTEXPR NonTrivialSortableWithComp() : value(0) {} NonTrivialSortableWithCompNonTrivialSortableWithComp66 TEST_CONSTEXPR NonTrivialSortableWithComp(int v) : value(v) {} NonTrivialSortableWithCompNonTrivialSortableWithComp67 TEST_CONSTEXPR NonTrivialSortableWithComp(const NonTrivialSortableWithComp& rhs) : value(rhs.value) {} 68 TEST_CONSTEXPR_CXX14 NonTrivialSortableWithComp& operator=(const NonTrivialSortableWithComp& rhs) { value = rhs.value; return *this; } 69 struct Comparator { operatorNonTrivialSortableWithComp::Comparator70 TEST_CONSTEXPR bool operator()(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) const { 71 return a.value / 10 < b.value / 10; 72 } 73 }; lessNonTrivialSortableWithComp74 static TEST_CONSTEXPR bool less(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) { 75 return a.value < b.value; 76 } 77 }; 78 79 static_assert(std::is_trivially_copyable<TrivialSortable>::value, ""); 80 static_assert(std::is_trivially_copyable<TrivialSortableWithComp>::value, ""); 81 static_assert(!std::is_trivially_copyable<NonTrivialSortable>::value, ""); 82 static_assert(!std::is_trivially_copyable<NonTrivialSortableWithComp>::value, ""); 83 84 #if TEST_STD_VER > 17 85 struct TracedCopy { 86 int copied = 0; 87 int data = 0; 88 89 constexpr TracedCopy() = default; TracedCopyTracedCopy90 constexpr TracedCopy(int i) : data(i) {} TracedCopyTracedCopy91 constexpr TracedCopy(const TracedCopy& other) : copied(other.copied + 1), data(other.data) {} 92 93 constexpr TracedCopy(TracedCopy&& other) = delete; 94 constexpr TracedCopy& operator=(TracedCopy&& other) = delete; 95 96 constexpr TracedCopy& operator=(const TracedCopy& other) { 97 copied = other.copied + 1; 98 data = other.data; 99 return *this; 100 } 101 copiedOnceTracedCopy102 constexpr bool copiedOnce() const { return copied == 1; } 103 104 constexpr bool operator==(const TracedCopy& o) const { return data == o.data; } 105 constexpr auto operator<=>(const TracedCopy& o) const { return data <=> o.data; } 106 }; 107 108 template <class Iter> 109 struct NonBorrowedRange { 110 int* data_; 111 size_t size_; 112 113 // TODO: some algorithms calls std::__copy 114 // std::__copy(contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>, contiguous_iterator<int*>) doesn't seem to work. 115 // It seems that it unwraps contiguous_iterator<int*> into int*, and then it failed because there is no == between int* and 116 // sentinel_wrapper<contiguous_iterator<int*>> 117 using Sent = std::conditional_t<std::contiguous_iterator<Iter>, Iter, sentinel_wrapper<Iter>>; 118 NonBorrowedRangeNonBorrowedRange119 constexpr NonBorrowedRange(int* d, size_t s) : data_{d}, size_{s} {} 120 beginNonBorrowedRange121 constexpr Iter begin() const { return Iter{data_}; }; endNonBorrowedRange122 constexpr Sent end() const { return Sent{Iter{data_ + size_}}; }; 123 }; 124 #endif // TEST_STD_VER > 17 125 126 #endif // SORTABLE_HELPERS_H 127