1b80f2dfdSKent Ross //===----------------------------------------------------------------------===//
2b80f2dfdSKent Ross //
3b80f2dfdSKent Ross // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b80f2dfdSKent Ross // See https://llvm.org/LICENSE.txt for license information.
5b80f2dfdSKent Ross // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b80f2dfdSKent Ross //
7b80f2dfdSKent Ross //===----------------------------------------------------------------------===//
8b80f2dfdSKent Ross
9b80f2dfdSKent Ross // <tuple>
10b80f2dfdSKent Ross
11b80f2dfdSKent Ross // template <class... Types> class tuple;
12b80f2dfdSKent Ross
13b80f2dfdSKent Ross // template<class... TTypes, class... UTypes>
14b80f2dfdSKent Ross // auto
15b80f2dfdSKent Ross // operator<=>(const tuple<TTypes...>& t, const tuple<UTypes...>& u);
16b80f2dfdSKent Ross
17d2baefaeSJoe Loser // UNSUPPORTED: c++03, c++11, c++14, c++17
184e00a192SCasey Carter
194e00a192SCasey Carter #include "test_macros.h"
204e00a192SCasey Carter
21*14324fa4SNikolas Klauser TEST_CLANG_DIAGNOSTIC_IGNORED("-Wsign-compare")
22*14324fa4SNikolas Klauser TEST_GCC_DIAGNOSTIC_IGNORED("-Wsign-compare")
23*14324fa4SNikolas Klauser TEST_MSVC_DIAGNOSTIC_IGNORED(4242 4244)
24b80f2dfdSKent Ross
25b80f2dfdSKent Ross #include <cassert>
26b80f2dfdSKent Ross #include <compare>
27b80f2dfdSKent Ross #include <limits>
28b80f2dfdSKent Ross #include <tuple>
29b80f2dfdSKent Ross #include <type_traits> // std::is_constant_evaluated
30b80f2dfdSKent Ross
31b80f2dfdSKent Ross // A custom three-way result type
32b80f2dfdSKent Ross struct CustomEquality {
operator ==(const CustomEquality &,int)33b80f2dfdSKent Ross friend constexpr bool operator==(const CustomEquality&, int) noexcept { return true; }
operator <(const CustomEquality &,int)34b80f2dfdSKent Ross friend constexpr bool operator<(const CustomEquality&, int) noexcept { return false; }
operator <(int,const CustomEquality &)35b80f2dfdSKent Ross friend constexpr bool operator<(int, const CustomEquality&) noexcept { return false; }
36b80f2dfdSKent Ross };
37b80f2dfdSKent Ross
test()38b80f2dfdSKent Ross constexpr bool test() {
39b80f2dfdSKent Ross // Empty tuple
40b80f2dfdSKent Ross {
41b80f2dfdSKent Ross typedef std::tuple<> T0;
42b80f2dfdSKent Ross // No member types yields strong ordering (all are equal).
43b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T0() <=> T0()), std::strong_ordering);
44b80f2dfdSKent Ross assert((T0() <=> T0()) == std::strong_ordering::equal);
45b80f2dfdSKent Ross }
46b80f2dfdSKent Ross // Mixed types with integers, which compare strongly ordered
47b80f2dfdSKent Ross {
48b80f2dfdSKent Ross typedef std::tuple<long> T1;
49b80f2dfdSKent Ross typedef std::tuple<short> T2;
50b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::strong_ordering);
51b80f2dfdSKent Ross assert((T1(1) <=> T2(1)) == std::strong_ordering::equal);
52b80f2dfdSKent Ross assert((T1(1) <=> T2(0)) == std::strong_ordering::greater);
53b80f2dfdSKent Ross assert((T1(1) <=> T2(2)) == std::strong_ordering::less);
54b80f2dfdSKent Ross }
55b80f2dfdSKent Ross {
56b80f2dfdSKent Ross typedef std::tuple<long, unsigned int> T1;
57b80f2dfdSKent Ross typedef std::tuple<short, unsigned long> T2;
58b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::strong_ordering);
59b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 2)) == std::strong_ordering::equal);
60b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(0, 2)) == std::strong_ordering::greater);
61b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(2, 2)) == std::strong_ordering::less);
62b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 1)) == std::strong_ordering::greater);
63b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 3)) == std::strong_ordering::less);
64b80f2dfdSKent Ross }
65b80f2dfdSKent Ross {
66b80f2dfdSKent Ross typedef std::tuple<long, int, unsigned short> T1;
67b80f2dfdSKent Ross typedef std::tuple<short, long, unsigned int> T2;
68b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::strong_ordering);
69b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 3)) == std::strong_ordering::equal);
70b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(0, 2, 3)) == std::strong_ordering::greater);
71b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(2, 2, 3)) == std::strong_ordering::less);
72b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 1, 3)) == std::strong_ordering::greater);
73b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 3, 3)) == std::strong_ordering::less);
74b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 2)) == std::strong_ordering::greater);
75b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 4)) == std::strong_ordering::less);
76b80f2dfdSKent Ross }
77b80f2dfdSKent Ross // Mixed types with floating point, which compare partially ordered
78b80f2dfdSKent Ross {
79b80f2dfdSKent Ross typedef std::tuple<long> T1;
80b80f2dfdSKent Ross typedef std::tuple<double> T2;
81b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
82b80f2dfdSKent Ross assert((T1(1) <=> T2(1)) == std::partial_ordering::equivalent);
83b80f2dfdSKent Ross assert((T1(1) <=> T2(0.9)) == std::partial_ordering::greater);
84b80f2dfdSKent Ross assert((T1(1) <=> T2(1.1)) == std::partial_ordering::less);
85b80f2dfdSKent Ross }
86b80f2dfdSKent Ross {
87b80f2dfdSKent Ross typedef std::tuple<long, float> T1;
88b80f2dfdSKent Ross typedef std::tuple<double, unsigned int> T2;
89b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
90b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 2)) == std::partial_ordering::equivalent);
91b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(0.9, 2)) == std::partial_ordering::greater);
92b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1.1, 2)) == std::partial_ordering::less);
93b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 1)) == std::partial_ordering::greater);
94b80f2dfdSKent Ross assert((T1(1, 2) <=> T2(1, 3)) == std::partial_ordering::less);
95b80f2dfdSKent Ross }
96b80f2dfdSKent Ross {
97b80f2dfdSKent Ross typedef std::tuple<short, float, double> T1;
98b80f2dfdSKent Ross typedef std::tuple<double, long, unsigned int> T2;
99b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
100b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 3)) == std::partial_ordering::equivalent);
101b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(0.9, 2, 3)) == std::partial_ordering::greater);
102b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1.1, 2, 3)) == std::partial_ordering::less);
103b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 1, 3)) == std::partial_ordering::greater);
104b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 3, 3)) == std::partial_ordering::less);
105b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 2)) == std::partial_ordering::greater);
106b80f2dfdSKent Ross assert((T1(1, 2, 3) <=> T2(1, 2, 4)) == std::partial_ordering::less);
107b80f2dfdSKent Ross }
108b80f2dfdSKent Ross {
109b80f2dfdSKent Ross typedef std::tuple<float> T1;
110b80f2dfdSKent Ross typedef std::tuple<double> T2;
111b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
112b80f2dfdSKent Ross // Comparisons with NaN and non-NaN are non-constexpr in GCC, so both sides must be NaN
113b80f2dfdSKent Ross assert((T1(nan) <=> T2(nan)) == std::partial_ordering::unordered);
114b80f2dfdSKent Ross }
115b80f2dfdSKent Ross {
116b80f2dfdSKent Ross typedef std::tuple<double, double> T1;
117b80f2dfdSKent Ross typedef std::tuple<float, float> T2;
118b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
119b80f2dfdSKent Ross assert((T1(nan, 2) <=> T2(nan, 2)) == std::partial_ordering::unordered);
120b80f2dfdSKent Ross assert((T1(1, nan) <=> T2(1, nan)) == std::partial_ordering::unordered);
121b80f2dfdSKent Ross }
122b80f2dfdSKent Ross {
123b80f2dfdSKent Ross typedef std::tuple<double, float, float> T1;
124b80f2dfdSKent Ross typedef std::tuple<double, double, float> T2;
125b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
126b80f2dfdSKent Ross assert((T1(nan, 2, 3) <=> T2(nan, 2, 3)) == std::partial_ordering::unordered);
127b80f2dfdSKent Ross assert((T1(1, nan, 3) <=> T2(1, nan, 3)) == std::partial_ordering::unordered);
128b80f2dfdSKent Ross assert((T1(1, 2, nan) <=> T2(1, 2, nan)) == std::partial_ordering::unordered);
129b80f2dfdSKent Ross }
130b80f2dfdSKent Ross // Ordering classes and synthesized three way comparison
131b80f2dfdSKent Ross {
132b80f2dfdSKent Ross typedef std::tuple<long, int, unsigned int> T1;
133b80f2dfdSKent Ross typedef std::tuple<int, long, unsigned short> T2;
134b80f2dfdSKent Ross // All strongly ordered members yields strong ordering.
135b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::strong_ordering);
136b80f2dfdSKent Ross }
137b80f2dfdSKent Ross {
138b80f2dfdSKent Ross struct WeakSpaceship {
139b80f2dfdSKent Ross constexpr bool operator==(const WeakSpaceship&) const { return true; }
140b80f2dfdSKent Ross constexpr std::weak_ordering operator<=>(const WeakSpaceship&) const { return std::weak_ordering::equivalent; }
141b80f2dfdSKent Ross };
142b80f2dfdSKent Ross {
143b80f2dfdSKent Ross typedef std::tuple<int, unsigned int, WeakSpaceship> T1;
144b80f2dfdSKent Ross typedef std::tuple<int, unsigned long, WeakSpaceship> T2;
145b80f2dfdSKent Ross // Strongly ordered members and a weakly ordered member yields weak ordering.
146b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::weak_ordering);
147b80f2dfdSKent Ross }
148b80f2dfdSKent Ross {
149b80f2dfdSKent Ross typedef std::tuple<unsigned int, int, WeakSpaceship> T1;
150b80f2dfdSKent Ross typedef std::tuple<double, long, WeakSpaceship> T2;
151b80f2dfdSKent Ross // Doubles are partially ordered, so one partial, one strong, and one weak ordering
152b80f2dfdSKent Ross // yields partial ordering.
153b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
154b80f2dfdSKent Ross }
155b80f2dfdSKent Ross }
156b80f2dfdSKent Ross {
157b80f2dfdSKent Ross struct NoSpaceship {
158b80f2dfdSKent Ross constexpr bool operator==(const NoSpaceship&) const { return true; }
159b80f2dfdSKent Ross constexpr bool operator<(const NoSpaceship&) const { return false; }
160b80f2dfdSKent Ross };
161b80f2dfdSKent Ross typedef std::tuple<int, unsigned int, NoSpaceship> T1;
162b80f2dfdSKent Ross typedef std::tuple<int, unsigned long, NoSpaceship> T2;
163b80f2dfdSKent Ross // Strongly ordered members and a weakly ordered member (synthesized) yields weak ordering.
164b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::weak_ordering);
165b80f2dfdSKent Ross }
166b80f2dfdSKent Ross {
167b80f2dfdSKent Ross struct SpaceshipNoEquals {
168b80f2dfdSKent Ross constexpr std::strong_ordering operator<=>(const SpaceshipNoEquals&) const { return std::strong_ordering::equal; }
169b80f2dfdSKent Ross constexpr bool operator<(const SpaceshipNoEquals&) const { return false; }
170b80f2dfdSKent Ross };
171b80f2dfdSKent Ross typedef std::tuple<int, unsigned int, SpaceshipNoEquals> T1;
172b80f2dfdSKent Ross typedef std::tuple<int, unsigned long, SpaceshipNoEquals> T2;
173b80f2dfdSKent Ross // Spaceship operator with no == operator falls back on the < operator and weak ordering.
174b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::weak_ordering);
175b80f2dfdSKent Ross }
176b80f2dfdSKent Ross {
177b80f2dfdSKent Ross struct CustomSpaceship {
178b80f2dfdSKent Ross constexpr CustomEquality operator<=>(const CustomSpaceship&) const { return CustomEquality(); }
179b80f2dfdSKent Ross };
180b80f2dfdSKent Ross typedef std::tuple<int, unsigned int, CustomSpaceship> T1;
181b80f2dfdSKent Ross typedef std::tuple<short, unsigned long, CustomSpaceship> T2;
182b80f2dfdSKent Ross typedef std::tuple<CustomSpaceship> T3;
183b80f2dfdSKent Ross // Custom three way return types cannot be used in synthesized three way comparison,
184b80f2dfdSKent Ross // but they can be used for (rewritten) operator< when synthesizing a weak ordering.
185b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::weak_ordering);
186b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T3() <=> T3()), std::weak_ordering);
187b80f2dfdSKent Ross }
188b80f2dfdSKent Ross {
189b80f2dfdSKent Ross typedef std::tuple<long, int> T1;
190b80f2dfdSKent Ross typedef std::tuple<long, unsigned int> T2;
191b80f2dfdSKent Ross // Even with the warning suppressed (-Wno-sign-compare) there should still be no <=> operator
192b80f2dfdSKent Ross // between signed and unsigned types, so we should end up with a synthesized weak ordering.
193b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::weak_ordering);
194b80f2dfdSKent Ross }
195b80f2dfdSKent Ross
196b80f2dfdSKent Ross #ifdef TEST_COMPILER_GCC
197b80f2dfdSKent Ross // GCC cannot evaluate NaN @ non-NaN constexpr, so test that runtime-only.
198b80f2dfdSKent Ross if (!std::is_constant_evaluated())
199b80f2dfdSKent Ross #endif
200b80f2dfdSKent Ross {
201b80f2dfdSKent Ross {
202b80f2dfdSKent Ross typedef std::tuple<double> T1;
203b80f2dfdSKent Ross typedef std::tuple<int> T2;
204b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
205b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
206b80f2dfdSKent Ross assert((T1(nan) <=> T2(1)) == std::partial_ordering::unordered);
207b80f2dfdSKent Ross }
208b80f2dfdSKent Ross {
209b80f2dfdSKent Ross typedef std::tuple<double, double> T1;
210b80f2dfdSKent Ross typedef std::tuple<int, int> T2;
211b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
212b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
213b80f2dfdSKent Ross assert((T1(nan, 2) <=> T2(1, 2)) == std::partial_ordering::unordered);
214b80f2dfdSKent Ross assert((T1(1, nan) <=> T2(1, 2)) == std::partial_ordering::unordered);
215b80f2dfdSKent Ross }
216b80f2dfdSKent Ross {
217b80f2dfdSKent Ross typedef std::tuple<double, double, double> T1;
218b80f2dfdSKent Ross typedef std::tuple<int, int, int> T2;
219b80f2dfdSKent Ross constexpr double nan = std::numeric_limits<double>::quiet_NaN();
220b80f2dfdSKent Ross ASSERT_SAME_TYPE(decltype(T1() <=> T2()), std::partial_ordering);
221b80f2dfdSKent Ross assert((T1(nan, 2, 3) <=> T2(1, 2, 3)) == std::partial_ordering::unordered);
222b80f2dfdSKent Ross assert((T1(1, nan, 3) <=> T2(1, 2, 3)) == std::partial_ordering::unordered);
223b80f2dfdSKent Ross assert((T1(1, 2, nan) <=> T2(1, 2, 3)) == std::partial_ordering::unordered);
224b80f2dfdSKent Ross }
225b80f2dfdSKent Ross }
226b80f2dfdSKent Ross
227b80f2dfdSKent Ross return true;
228b80f2dfdSKent Ross }
229b80f2dfdSKent Ross
main(int,char **)230b80f2dfdSKent Ross int main(int, char**) {
231b80f2dfdSKent Ross test();
232b80f2dfdSKent Ross static_assert(test());
233b80f2dfdSKent Ross
234b80f2dfdSKent Ross return 0;
235b80f2dfdSKent Ross }
236