]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/25_algorithms/minmax/constrained.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 25_algorithms / minmax / constrained.cc
CommitLineData
83ffe9cd 1// Copyright (C) 2020-2023 Free Software Foundation, Inc.
bc464641
PP
2//
3// This file is part of the GNU ISO C++ Library. This library is free
4// software; you can redistribute it and/or modify it under the
5// terms of the GNU General Public License as published by the
6// Free Software Foundation; either version 3, or (at your option)
7// any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License along
15// with this library; see the file COPYING3. If not see
16// <http://www.gnu.org/licenses/>.
17
18// { dg-options "-std=gnu++2a" }
19// { dg-do run { target c++2a } }
20
21#include <algorithm>
cc9c94d4 22#include <string>
7e76cef8 23#include <utility>
cc9c94d4 24#include <vector>
bc464641
PP
25#include <testsuite_hooks.h>
26#include <testsuite_iterators.h>
27
28using __gnu_test::test_container;
29using __gnu_test::test_range;
30using __gnu_test::input_iterator_wrapper;
31
32namespace ranges = std::ranges;
33
34template<typename T1, typename T2>
35constexpr bool
36operator==(const ranges::minmax_result<T1>& lhs,
37 const ranges::minmax_result<T2>& rhs)
38{
39 return (lhs.min == rhs.min
40 && rhs.max == rhs.max);
41}
42
43
44struct X
45{
46 int i, j;
47};
48
49using res_t = ranges::minmax_result<int>;
50
51void
52test01()
53{
54 VERIFY( ranges::minmax(1, 2) == res_t(1,2) );
55 VERIFY( ranges::minmax(2, 1) == res_t(1,2) );
56 VERIFY( ranges::minmax(1, 2, ranges::greater{}) == res_t(2,1) );
57 VERIFY( ranges::minmax(1, 2, ranges::greater{}, std::negate<>{}) == res_t(1,2) );
58 VERIFY( ranges::minmax(1, 2, {}, std::negate<>{}) == res_t(2,1) );
59 VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).min.j == 2 );
60 VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).max.j == 3 );
61}
62
63void
64test02()
65{
66 int x[] = {1,2,3,4};
67 do
68 {
69 test_range<int, input_iterator_wrapper> cx(x);
70 VERIFY( ranges::minmax(cx) == res_t(1,4) );
71 cx.bounds.first = x;
72 VERIFY( ranges::minmax(cx, ranges::greater{}) == res_t(4,1) );
73 cx.bounds.first = x;
74 VERIFY( ranges::minmax(cx, {}, std::negate<>{}) == res_t(4,1));
75 cx.bounds.first = x;
76 VERIFY( ranges::minmax(cx, ranges::greater{}, std::negate<>{})
77 == res_t(1,4) );
78 } while (ranges::next_permutation(x).found);
79
80 constexpr X y[] = {{1,5},{1,2},{1,3}};
81 static_assert(ranges::minmax(y, {}, &X::i).min.j == 5);
82 static_assert(ranges::minmax(y, {}, &X::i).max.j == 3);
83}
84
85void
86test03()
87{
88 VERIFY( ranges::minmax({2,3,1,4}) == res_t(1,4) );
89 VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}) == res_t(4,1) );
90 VERIFY( ranges::minmax({2,3,1,4}, {}, std::negate<>{}) == res_t(4,1) );
91 VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}, std::negate<>{})
92 == res_t(1,4) );
93}
94
cc9c94d4
PP
95void
96test04()
97{
98 // Verify we perform at most 3*N/2 applications of the comparison predicate.
99 static int counter;
100 struct counted_less
101 { bool operator()(int a, int b) { ++counter; return a < b; } };
102
103 ranges::minmax({1,2}, counted_less{});
104 VERIFY( counter == 1 );
105
106 counter = 0;
107 ranges::minmax({1,2,3}, counted_less{});
108 VERIFY( counter == 3 );
109
110 counter = 0;
111 ranges::minmax({1,2,3,4,5,6,7,8,9,10}, counted_less{});
112 VERIFY( counter <= 15 );
113
114 counter = 0;
115 ranges::minmax({10,9,8,7,6,5,4,3,2,1}, counted_less{});
116 VERIFY( counter <= 15 );
117}
118
119void
120test05()
121{
122 // PR libstdc++/100387
123 using namespace std::literals::string_literals;
124 auto comp = [](const auto& a, const auto& b) {
125 return a.size() == b.size() ? a.front() < b.front() : a.size() > b.size();
126 };
127 auto result = ranges::minmax({"b"s, "a"s}, comp);
128 VERIFY( result.min == "a"s && result.max == "b"s );
129 result = ranges::minmax({"c"s, "b"s, "a"s}, comp);
130 VERIFY( result.min == "a"s && result.max == "c"s );
131}
132
7e76cef8
PP
133struct A {
134 A() = delete;
135 A(int i) : i(i) { }
136 A(const A&) = default;
137 A(A&& other) : A(std::as_const(other)) { ++move_count; }
138 A& operator=(const A&) = default;
139 A& operator=(A&& other) {
140 ++move_count;
141 return *this = std::as_const(other);
142 };
143 friend auto operator<=>(const A&, const A&) = default;
144 static inline int move_count = 0;
145 int i;
146};
147
148void
149test06()
150{
151 // PR libstdc++/104858
152 // Verify ranges::minmax doesn't dereference the iterator for the first
153 // element in the range twice.
154 A a(42);
155 ranges::subrange r = {std::move_iterator(&a), std::move_sentinel(&a + 1)};
156 auto result = ranges::minmax(r);
157 VERIFY( A::move_count == 1 );
158 VERIFY( result.min.i == 42 && result.max.i == 42 );
159}
160
bc464641
PP
161int
162main()
163{
164 test01();
165 test02();
166 test03();
cc9c94d4
PP
167 test04();
168 test05();
7e76cef8 169 test06();
bc464641 170}