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