Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.swap.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for swap, swap_ranges, iter_swap
30#include <cstring> // for size_t, strlen()
31
32#include <rw_alg_test.h>
33#include <rw_value.h> // for UserClass
34#include <rw_driver.h> // for rw_test()
35
36
38
39// disable explicit instantiation for compilers (like MSVC)
40// that can't handle it
41#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
42
43template
44void
46
47template
49swap_ranges (FwdIter<assign<base<cpy_ctor> > >,
52
53template
54void
55iter_swap (FwdIter<assign<base<cpy_ctor> > >,
57
58#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
59
60} // namespace std
61
62
64template <class T, class ForwardIterator1, class ForwardIterator2>
66 const char* seq,
67 ForwardIterator1 /* dummy */,
68 ForwardIterator2 /* dummy */,
69 const T* /* dummy */,
70 bool it_swap,
71 const char* it1name,
72 const char* it2name,
73 const char* fname)
74{
75 // generate sequential values for each default constructed T
76 const std::size_t nseq = std::strlen (seq);
77
78 // construct a sequence of `nseq' elements to pass to swap
79 T* const tseq = T::from_char (seq, nseq + 1);
80
81 int a_val, b_val;
82 bool success = true;
83 std::size_t i = 1;
84 for ( ; i < nseq; ++i) {
85
86 const ForwardIterator1 it1 =
87 make_iter (tseq, tseq, tseq + nseq, it1);
88
89 const ForwardIterator2 it2 =
90 make_iter (tseq + i, tseq, tseq + nseq, it2);
91
92 a_val = (*it1).data_.val_;
93 b_val = (*it2).data_.val_;
94
95 it_swap ? std::iter_swap (it1, it2) : std::swap(*it1, *it2);
96
97 // verify 25.2.2, p2, p7
98 success = a_val == (*it2).data_.val_ && b_val == (*it1).data_.val_;
99 if (!success)
100 break;
101 }
102
103 rw_assert (success, 0, line,
104 "%s<%s%{?}, %s%{;}>(%#c, %#c): got: { %#c, %#c } "
105 "expected: { %5$#c, %4$#c } at step %zu",
106 fname, it1name, it_swap, it2name, a_val, b_val,
107 tseq->data_.val_, (tseq + i)->data_.val_, i);
108
109 delete[] tseq;
110}
111
112template <class T, class ForwardIterator1, class ForwardIterator2>
113void test_iter_swap (ForwardIterator1 it1, ForwardIterator2 it2,
114 const T*, bool it_swap)
115{
116 const char* const it1name = it_swap ? type_name (it1, (T*)0) : "UserClass";
117 const char* const it2name = it_swap ? type_name (it2, (T*)0) : "UserClass";
118 const char* const fname = it_swap ? "iter_swap" : "swap";
119
120 rw_info (0, 0, 0, "std::%s (%s, %s)", fname, it1name, it2name);
121
122#undef TEST
123#define TEST(seq) \
124 test_iter_swap (__LINE__, seq, it1, it2, (T*)0, it_swap, \
125 it1name, it2name, fname)
126
127 TEST("ab");
128 TEST("abc");
129 TEST("abcd");
130 TEST("abcde");
131 TEST("abcdef");
132 TEST("abcdefg");
133 TEST("abcdefgh");
134 TEST("abcdefghi");
135 TEST("abcdefghij");
136 TEST("abcdefghijk");
137}
138
139
141template <class T, class ForwardIterator1, class ForwardIterator2>
143 const char* seq1,
144 const char* seq2,
145 ForwardIterator1 it1,
146 ForwardIterator2 it2,
147 const T* /* dummy */,
148 const char* it1name,
149 const char* it2name)
150{
151 const std::size_t nseq = std::strlen (seq1);
152
153 // construct a sequence of `nseq' elements to pass to swap_ranges
154 T* const tseq1 = T::from_char (seq1, nseq + 1);
155 T* const tseq2 = T::from_char (seq2, nseq + 1);
156
157 const ForwardIterator1 first1 =
158 make_iter (tseq1, tseq1, tseq1 + nseq, it1);
159 const ForwardIterator1 last1 =
160 make_iter (tseq1 + nseq, tseq1, tseq1 + nseq, it1);
161 const ForwardIterator2 first2 =
162 make_iter (tseq2, tseq2, tseq2 + nseq, it2);
163 const ForwardIterator2 last2 =
164 make_iter (tseq2 + nseq, tseq2, tseq2 + nseq, it2);
165
166 // silence bogus EDG eccp remark #550-D: variable was set
167 // but never used
168 _RWSTD_UNUSED (last2);
169
170 T a, b;
171
172 std::size_t last_n_op_assign = T::n_total_op_assign_;
173
174 std::swap (a, b);
175
176 std::size_t assigns_per_swap = T::n_total_op_assign_ - last_n_op_assign;
177
178 last_n_op_assign = T::n_total_op_assign_;
179
180 // exercise 25.2.3 - std::swap_ranges()
181 const ForwardIterator2 res = std::swap_ranges(first1, last1, first2);
182
183 // silence bogus EDG eccp remark #550-D: variable was set
184 // but never used
186
187 // check the returned value, 25.2.2 p5
188 bool success = res.cur_ == last2.cur_;
189 rw_assert (success, 0, line,
190 "swap_ranges<%s, %s>(\"%s\", \"%s\") == first + %td, "
191 "got first + %td",
192 it1name, it2name, seq1, seq2, res.cur_ - tseq2,
193 last2.cur_ - tseq2);
194
195 // check that the sequences were swapped, 25.2.2 p4
196 std::size_t i = 0;
197 for ( ; i < nseq; ++i) {
198 success = (tseq1 + i)->data_.val_ == seq2[i]
199 && (tseq2 + i)->data_.val_ == seq1[i];
200 if (!success)
201 break;
202 }
203
204 rw_assert (success, 0, line,
205 "swap_ranges<%s, %s>(\"%s\", \"%s\") mismatch at pos %zu "
206 "got { %#c, %#c }, expected { %#c, %#c }",
207 it1name, it2name, seq1, seq2, i, (tseq1 + i)->data_.val_,
208 (tseq2 + i)->data_.val_, seq2[i], seq1[i]);
209
210 // check the complexity, 25.2.2 p6
211 std::size_t swaps_per_swap_ranges =
212 (T::n_total_op_assign_ - last_n_op_assign) / assigns_per_swap;
213 rw_assert (swaps_per_swap_ranges == nseq, 0, line,
214 "swap_ranges<%s, %s>(\"%s\", \"%s\") complexity: "
215 "%zu, expected %zu swaps",
216 it1name, it2name, seq1, seq2, swaps_per_swap_ranges, nseq);
217
218 delete[] tseq1;
219 delete[] tseq2;
220}
221
222
224template <class T, class ForwardIterator1, class ForwardIterator2>
225void test_swap_ranges (ForwardIterator1 it1,
226 ForwardIterator2 it2,
227 const T* /* dummy */)
228{
229 static const char* const it1name = type_name (it1, (T*)0);
230 static const char* const it2name = type_name (it2, (T*)0);
231
232 rw_info (0, 0, 0,
233 "std::swap_ranges (%s, %1$s, %s)", it1name, it2name);
234
235#undef TEST
236#define TEST(seq1, seq2) \
237 test_swap_ranges (__LINE__, seq1, seq2, it1, it2, (T*)0, \
238 it1name, it2name)
239
240 TEST("", "");
241 TEST("a", "z");
242 TEST("ab", "zy");
243 TEST("abc", "zyx");
244 TEST("abcd", "zyxw");
245 TEST("abcde", "zyxwv");
246 TEST("abcdef", "zyxwvu");
247 TEST("abcdefg", "zyxwvut");
248 TEST("abcdefgh", "zyxwvuts");
249 TEST("abcdefghi", "zyxwvutsr");
250 TEST("abcdefghij", "zyxwvutsrq");
251 TEST("abcdefghijk", "zyxwvutsrqp");
252 TEST("abcdefghijkl", "zyxwvutsrqpo");
253 TEST("abcdefghijklm", "zyxwvutsrqpon");
254}
255
256
258/* extern */ int rw_opt_no_swap; // --no-swap
259/* extern */ int rw_opt_no_swap_ranges; // --no-swap_ranges
260/* extern */ int rw_opt_no_iter_swap; // --no-iter_swap
261/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
262/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
263/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
264
265template <class T, class ForwardIterator1>
266void test_swap (ForwardIterator1 it1, const T*, bool test_ranges)
267{
268 if (rw_opt_no_fwd_iter) {
269 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
270 }
271 else {
272 if (test_ranges)
273 test_swap_ranges (it1, FwdIter<T>(), (T*)0);
274 else
275 test_iter_swap (it1, FwdIter<T>(), (T*)0, true);
276 }
277
279 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
280 }
281 else {
282 if (test_ranges)
283 test_swap_ranges (it1, BidirIter<T>(), (T*)0);
284 else
285 test_iter_swap (it1, BidirIter<T>(), (T*)0, true);
286 }
287
288 if (rw_opt_no_rnd_iter) {
289 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
290 }
291 else {
292 if (test_ranges)
294 else
295 test_iter_swap (it1, RandomAccessIter<T>(), (T*)0, true);
296 }
297}
298
299
301template <class T>
302void test_swap (const T*, bool test_ranges)
303{
304 if (rw_opt_no_fwd_iter) {
305 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
306 }
307 else {
308 test_swap (FwdIter<T>(), (T*)0, test_ranges);
309 }
310
312 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
313 }
314 else {
315 test_swap (BidirIter<T>(), (T*)0, test_ranges);
316 }
317
318 if (rw_opt_no_rnd_iter) {
319 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
320 }
321 else {
322 test_swap (RandomAccessIter<T>(), (T*)0, test_ranges);
323 }
324}
325
326
328static int
329run_test (int, char*[])
330{
331 if (rw_opt_no_swap) {
332 rw_note (0, __FILE__, __LINE__, "std::swap test disabled");
333 }
334 else {
335 rw_info (0, 0, 0, "template <class T> void swap (T&, T&)");
336
338 (UserClass*)0, false);
339 }
340
342 rw_note (0, __FILE__, __LINE__, "std::swap_ranges test disabled");
343 }
344 else {
345 rw_info (0, 0, 0,
346 "template <class %s, class %s> %2$s "
347 "swap_ranges (%1$s, %1$s, %2$s)",
348 "ForwardIterator1", "ForwardIterator2");
349
350 test_swap ((UserClass*)0, true);
351 }
352
354 rw_note (0, __FILE__, __LINE__, "std::iter_swap test disabled");
355 }
356 else {
357 rw_info (0, 0, 0,
358 "template <class %s, class %s> void iter_swap (%1$s, %2$s)",
359 "ForwardIterator1", "ForwardIterator2");
360
361 test_swap ((UserClass*)0, false);
362 }
363
364 return 0;
365}
366
367
369int main (int argc, char *argv[])
370{
371 return rw_test (argc, argv, __FILE__,
372 "lib.alg.swap",
373 0 /* no comment */, run_test,
374 "|-no-swap# "
375 "|-no-swap_ranges# "
376 "|-no-iter_swap# "
377 "|-no-ForwardIterator# "
378 "|-no-BidirectionalIterator# "
379 "|-no-RandomAccessIterator",
386}
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define a
Definition 17.names.cpp:109
#define b
Definition 17.names.cpp:110
void test_swap()
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(seq)
int rw_opt_no_swap_ranges
Definition 25.swap.cpp:259
int rw_opt_no_fwd_iter
Definition 25.swap.cpp:261
int rw_opt_no_swap
Definition 25.swap.cpp:258
int rw_opt_no_rnd_iter
Definition 25.swap.cpp:263
int rw_opt_no_bidir_iter
Definition 25.swap.cpp:262
void test_iter_swap(int line, const char *seq, ForwardIterator1, ForwardIterator2, const T *, bool it_swap, const char *it1name, const char *it2name, const char *fname)
Definition 25.swap.cpp:65
void test_swap_ranges(int line, const char *seq1, const char *seq2, ForwardIterator1 it1, ForwardIterator2 it2, const T *, const char *it1name, const char *it2name)
Definition 25.swap.cpp:142
int rw_opt_no_iter_swap
Definition 25.swap.cpp:260
const char * type_name()
#define main
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
Definition json.h:5363
T * make_iter(T *cur, const T *, const T *, T *)
_TEST_EXPORT int rw_test(int argc, char *argv[], const char *filename, const char *clause, const char *comment, int(*testfun)(int, char **), const char *optspec,...)
_TEST_EXPORT int rw_info(int, const char *, int, const char *,...)
Definition driver.cpp:1681
_TEST_EXPORT int rw_note(int, const char *, int, const char *,...)
Definition driver.cpp:1664
_TEST_EXPORT int rw_assert(int, const char *, int, const char *,...)
Definition driver.cpp:1630