OXYGENHUB
◆ main openmsx / src / unittest / stl_test.cc
6.0 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#include "catch.hpp"
2
#include "stl.hh"
3
4
#include <list>
5
#include <ranges>
6
7
struct S {
8
	S()                        { ++default_constructed; }
9
	S(const S&)                { ++copy_constructed; }
10
	S(S&&) noexcept            { ++move_constructed; }
11
	S& operator=(const S&)     { ++copy_assignment; return *this; }
12
	S& operator=(S&&) noexcept { ++move_assignment; return *this; }
13
	~S()                       { ++destructed; }
14
15
	static void reset() {
16
		default_constructed = 0;
17
		copy_constructed = 0;
18
		move_constructed = 0;
19
		copy_assignment = 0;
20
		move_assignment = 0;
21
		destructed = 0;
22
	}
23
24
	static inline int default_constructed = 0;
25
	static inline int copy_constructed = 0;
26
	static inline int move_constructed = 0;
27
	static inline int copy_assignment = 0;
28
	static inline int move_assignment = 0;
29
	static inline int destructed = 0;
30
};
31
32
33
TEST_CASE("append")
34
{
35
	std::vector<int> v;
36
	std::vector<int> v0;
37
	std::vector<int> v123 = {1, 2, 3};
38
	std::vector<int> v45 = {4, 5};
39
40
	SECTION("non-empty + non-empty") {
41
		append(v123, v45);
42
		CHECK(v123 == std::vector<int>{1, 2, 3, 4, 5});
43
	}
44
	SECTION("non-empty + empty") {
45
		append(v123, v0);
46
		CHECK(v123 == std::vector<int>{1, 2, 3});
47
	}
48
	SECTION("empty + non-empty") {
49
		append(v, v45);
50
		CHECK(v == std::vector<int>{4, 5});
51
	}
52
	SECTION("empty + empty") {
53
		append(v, v0);
54
		CHECK(v == std::vector<int>{});
55
	}
56
	SECTION("non-empty + view") {
57
		append(v45, std::views::drop(v123, 1));
58
		CHECK(v45 == std::vector<int>{4, 5, 2, 3});
59
	}
60
	SECTION("empty + l-value") {
61
		{
62
			S::reset();
63
			std::vector<S> v1;
64
			std::vector<S> v2 = {S(), S()};
65
			CHECK(S::default_constructed == 2);
66
			CHECK(S::copy_constructed    == 2);
67
			CHECK(S::move_constructed    == 0);
68
			CHECK(S::copy_assignment     == 0);
69
			CHECK(S::move_assignment     == 0);
70
			CHECK(S::destructed          == 2);
71
			S::reset();
72
73
			append(v1, v2);
74
			CHECK(S::default_constructed == 0);
75
			CHECK(S::copy_constructed    == 2);
76
			CHECK(S::move_constructed    == 0);
77
			CHECK(S::copy_assignment     == 0);
78
			CHECK(S::move_assignment     == 0);
79
			CHECK(S::destructed          == 0);
80
			S::reset();
81
		}
82
		CHECK(S::default_constructed == 0);
83
		CHECK(S::copy_constructed    == 0);
84
		CHECK(S::move_constructed    == 0);
85
		CHECK(S::copy_assignment     == 0);
86
		CHECK(S::move_assignment     == 0);
87
		CHECK(S::destructed          == 4);
88
	}
89
	SECTION("empty + r-value") {
90
		{
91
			S::reset();
92
			std::vector<S> v1;
93
			std::vector<S> v2 = {S(), S()};
94
			CHECK(S::default_constructed == 2);
95
			CHECK(S::copy_constructed    == 2);
96
			CHECK(S::move_constructed    == 0);
97
			CHECK(S::copy_assignment     == 0);
98
			CHECK(S::move_assignment     == 0);
99
			CHECK(S::destructed          == 2);
100
			S::reset();
101
102
			append(v1, std::move(v2));
103
			CHECK(S::default_constructed == 0);
104
			CHECK(S::copy_constructed    == 0);
105
			CHECK(S::move_constructed    == 0);
106
			CHECK(S::copy_assignment     == 0);
107
			CHECK(S::move_assignment     == 0);
108
			CHECK(S::destructed          == 0);
109
			S::reset();
110
		}
111
		CHECK(S::default_constructed == 0);
112
		CHECK(S::copy_constructed    == 0);
113
		CHECK(S::move_constructed    == 0);
114
		CHECK(S::copy_assignment     == 0);
115
		CHECK(S::move_assignment     == 0);
116
		CHECK(S::destructed          == 2);
117
	}
118
}
119
120
121
TEST_CASE("to_vector: from list")
122
{
123
	SECTION("deduce type") {
124
		std::list<int> l = {1, 2, 3};
125
		auto v = to_vector(l);
126
		CHECK(v.size() == 3);
127
		CHECK(v[0] == 1);
128
		CHECK(v[1] == 2);
129
		CHECK(v[2] == 3);
130
		CHECK(std::is_same_v<decltype(v)::value_type, int>);
131
	}
132
	SECTION("convert type") {
133
		std::list<int> l = {1, 2, 3};
134
		auto v = to_vector<char>(l);
135
		CHECK(v.size() == 3);
136
		CHECK(v[0] == 1);
137
		CHECK(v[1] == 2);
138
		CHECK(v[2] == 3);
139
		CHECK(std::is_same_v<decltype(v)::value_type, char>);
140
	}
141
}
142
143
TEST_CASE("to_vector: from view")
144
{
145
	std::vector<int> v1 = {1, 2, 3};
146
	SECTION("deduce type") {
147
		auto v = to_vector(std::views::drop(v1, 2));
148
		CHECK(v.size() == 1);
149
		CHECK(v[0] == 3);
150
		CHECK(std::is_same_v<decltype(v)::value_type, int>);
151
	}
152
	SECTION("convert type") {
153
		auto v = to_vector<long long>(std::views::drop(v1, 1));
154
		CHECK(v.size() == 2);
155
		CHECK(v[0] == 2LL);
156
		CHECK(v[1] == 3LL);
157
		CHECK(std::is_same_v<decltype(v)::value_type, long long>);
158
	}
159
}
160
161
162
TEST_CASE("to_vector: optimized r-value")
163
{
164
	SECTION("l-value") {
165
		S::reset();
166
		{
167
			std::vector<S> v1 = {S(), S(), S()};
168
			CHECK(S::default_constructed == 3);
169
			CHECK(S::copy_constructed    == 3);
170
			CHECK(S::move_constructed    == 0);
171
			CHECK(S::copy_assignment     == 0);
172
			CHECK(S::move_assignment     == 0);
173
			CHECK(S::destructed          == 3);
174
			S::reset();
175
176
			auto v = to_vector(v1);
177
			CHECK(S::default_constructed == 0);
178
			CHECK(S::copy_constructed    == 3);
179
			CHECK(S::move_constructed    == 0);
180
			CHECK(S::copy_assignment     == 0);
181
			CHECK(S::move_assignment     == 0);
182
			CHECK(S::destructed          == 0);
183
			S::reset();
184
		}
185
		CHECK(S::default_constructed == 0);
186
		CHECK(S::copy_constructed    == 0);
187
		CHECK(S::move_constructed    == 0);
188
		CHECK(S::copy_assignment     == 0);
189
		CHECK(S::move_assignment     == 0);
190
		CHECK(S::destructed          == 6);
191
	}
192
	SECTION("r-value") {
193
		S::reset();
194
		{
195
			std::vector<S> v1 = {S(), S(), S()};
196
			CHECK(S::default_constructed == 3);
197
			CHECK(S::copy_constructed    == 3);
198
			CHECK(S::move_constructed    == 0);
199
			CHECK(S::copy_assignment     == 0);
200
			CHECK(S::move_assignment     == 0);
201
			CHECK(S::destructed          == 3);
202
			S::reset();
203
204
			auto v = to_vector(std::move(v1));
205
			CHECK(S::default_constructed == 0);
206
			CHECK(S::copy_constructed    == 0);
207
			CHECK(S::move_constructed    == 0);
208
			CHECK(S::copy_assignment     == 0);
209
			CHECK(S::move_assignment     == 0);
210
			CHECK(S::destructed          == 0);
211
			S::reset();
212
		}
213
		CHECK(S::default_constructed == 0);
214
		CHECK(S::copy_constructed    == 0);
215
		CHECK(S::move_constructed    == 0);
216
		CHECK(S::copy_assignment     == 0);
217
		CHECK(S::move_assignment     == 0);
218
		CHECK(S::destructed          == 3);
219
	}
220
}
221
222
223
// check quality of generated code
224
#if 0
225
std::vector<int> check1(const std::vector<int>& v)
226
{
227
	return to_vector(std::views::drop(v, 1));
228
}
229
std::vector<int> check2(const std::vector<int>& v)
230
{
231
	return std::vector<int>(begin(v) + 1, end(v));
232
}
233
#endif