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 <cstddef> |
13 | #include <type_traits> |
14 | |
15 | #include "test_macros.h" |
16 | |
17 | #if TEST_STD_VER > 17 |
18 | #include <compare> |
19 | #include <iterator> |
20 | #include "test_iterators.h" |
21 | #endif |
22 | |
23 | struct TrivialSortable { |
24 | int value; |
25 | TEST_CONSTEXPR TrivialSortable() : value(0) {} |
26 | TEST_CONSTEXPR TrivialSortable(int v) : value(v) {} |
27 | friend TEST_CONSTEXPR bool operator<(const TrivialSortable& a, const TrivialSortable& b) { |
28 | return a.value / 10 < b.value / 10; |
29 | } |
30 | static TEST_CONSTEXPR bool less(const TrivialSortable& a, const TrivialSortable& b) { |
31 | return a.value < b.value; |
32 | } |
33 | }; |
34 | |
35 | struct NonTrivialSortable { |
36 | int value; |
37 | TEST_CONSTEXPR NonTrivialSortable() : value(0) {} |
38 | TEST_CONSTEXPR NonTrivialSortable(int v) : value(v) {} |
39 | TEST_CONSTEXPR NonTrivialSortable(const NonTrivialSortable& rhs) : value(rhs.value) {} |
40 | TEST_CONSTEXPR_CXX14 NonTrivialSortable& operator=(const NonTrivialSortable& rhs) { value = rhs.value; return *this; } |
41 | friend TEST_CONSTEXPR bool operator<(const NonTrivialSortable& a, const NonTrivialSortable& b) { |
42 | return a.value / 10 < b.value / 10; |
43 | } |
44 | static TEST_CONSTEXPR bool less(const NonTrivialSortable& a, const NonTrivialSortable& b) { |
45 | return a.value < b.value; |
46 | } |
47 | }; |
48 | |
49 | |
50 | struct TrivialSortableWithComp { |
51 | int value; |
52 | TEST_CONSTEXPR TrivialSortableWithComp() : value(0) {} |
53 | TEST_CONSTEXPR TrivialSortableWithComp(int v) : value(v) {} |
54 | struct Comparator { |
55 | TEST_CONSTEXPR bool operator()(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) const { |
56 | return a.value / 10 < b.value / 10; |
57 | } |
58 | }; |
59 | static TEST_CONSTEXPR bool less(const TrivialSortableWithComp& a, const TrivialSortableWithComp& b) { |
60 | return a.value < b.value; |
61 | } |
62 | }; |
63 | |
64 | struct NonTrivialSortableWithComp { |
65 | int value; |
66 | TEST_CONSTEXPR NonTrivialSortableWithComp() : value(0) {} |
67 | TEST_CONSTEXPR NonTrivialSortableWithComp(int v) : value(v) {} |
68 | TEST_CONSTEXPR NonTrivialSortableWithComp(const NonTrivialSortableWithComp& rhs) : value(rhs.value) {} |
69 | TEST_CONSTEXPR_CXX14 NonTrivialSortableWithComp& operator=(const NonTrivialSortableWithComp& rhs) { value = rhs.value; return *this; } |
70 | struct Comparator { |
71 | TEST_CONSTEXPR bool operator()(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) const { |
72 | return a.value / 10 < b.value / 10; |
73 | } |
74 | }; |
75 | static TEST_CONSTEXPR bool less(const NonTrivialSortableWithComp& a, const NonTrivialSortableWithComp& b) { |
76 | return a.value < b.value; |
77 | } |
78 | }; |
79 | |
80 | static_assert(std::is_trivially_copyable<TrivialSortable>::value, "" ); |
81 | static_assert(std::is_trivially_copyable<TrivialSortableWithComp>::value, "" ); |
82 | static_assert(!std::is_trivially_copyable<NonTrivialSortable>::value, "" ); |
83 | static_assert(!std::is_trivially_copyable<NonTrivialSortableWithComp>::value, "" ); |
84 | |
85 | #if TEST_STD_VER > 17 |
86 | struct TracedCopy { |
87 | int copied = 0; |
88 | int data = 0; |
89 | |
90 | constexpr TracedCopy() = default; |
91 | constexpr TracedCopy(int i) : data(i) {} |
92 | constexpr TracedCopy(const TracedCopy& other) : copied(other.copied + 1), data(other.data) {} |
93 | |
94 | constexpr TracedCopy(TracedCopy&& other) = delete; |
95 | constexpr TracedCopy& operator=(TracedCopy&& other) = delete; |
96 | |
97 | constexpr TracedCopy& operator=(const TracedCopy& other) { |
98 | copied = other.copied + 1; |
99 | data = other.data; |
100 | return *this; |
101 | } |
102 | |
103 | constexpr bool copiedOnce() const { return copied == 1; } |
104 | |
105 | constexpr bool operator==(const TracedCopy& o) const { return data == o.data; } |
106 | constexpr auto operator<=>(const TracedCopy& o) const { return data <=> o.data; } |
107 | }; |
108 | |
109 | template <class Iter> |
110 | struct NonBorrowedRange { |
111 | int* data_; |
112 | std::size_t size_; |
113 | |
114 | // TODO: some algorithms calls std::__copy |
115 | // std::__copy(contiguous_iterator<int*>, sentinel_wrapper<contiguous_iterator<int*>>, contiguous_iterator<int*>) doesn't seem to work. |
116 | // It seems that it unwraps contiguous_iterator<int*> into int*, and then it failed because there is no == between int* and |
117 | // sentinel_wrapper<contiguous_iterator<int*>> |
118 | using Sent = std::conditional_t<std::contiguous_iterator<Iter>, Iter, sentinel_wrapper<Iter>>; |
119 | |
120 | constexpr NonBorrowedRange(int* d, std::size_t s) : data_{d}, size_{s} {} |
121 | |
122 | constexpr Iter begin() const { return Iter{data_}; }; |
123 | constexpr Sent end() const { return Sent{Iter{data_ + size_}}; }; |
124 | }; |
125 | #endif // TEST_STD_VER > 17 |
126 | |
127 | #endif // SORTABLE_HELPERS_H |
128 | |