Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.remove.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for remove(), remove_copy(), ...
30#include <cstring> // for 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
39
40// disable explicit instantiation for compilers (like MSVC)
41// that can't handle it
42#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
43
44template
46remove (FwdIter<eq_comp<assign<base<> > > >,
48 const eq_comp<assign<base<> > >&);
49
50template
52remove_if (FwdIter<eq_comp<assign<base<> > > >,
55
56template
58remove_copy (InputIter<eq_comp<assign<base<> > > >,
61 const eq_comp<assign<base<> > >&);
62
63template
65remove_copy_if (InputIter<eq_comp<assign<base<> > > >,
69
70#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
71
72} // namespace std
73
74
76// names of tested functions
77const char* const fnames[] = { "remove", "remove_copy" };
78const char* const fnames_if[] = { "remove_if", "remove_copy_if" };
79
80// tags to select remove or remove_copy at compile time
81struct RemoveTag {
82 enum { fname_inx = 0 };
84};
85
87 enum { fname_inx = 1 };
89};
90
91// used as a dummy template argument to test functions exercising remove()
92// and remove_if() (to differentiate from remove_copy() and remove_copy_if())
93struct NoIterator { };
94const char* type_name (NoIterator, const UserClass*)
95{
96 return 0;
97}
98
99
100typedef unsigned char UChar;
101
102
103// predicate used as an argument to remove_if() and remove_copy_if()
104template <class T>
106{
107 static std::size_t funcalls_;
108
109 EqualityPredicate (const T &val, int /* dummy */)
110 : val_ (val) {
111 funcalls_ = 0;
112 }
113
114 class ConvertibleToBool {
115 bool result_;
116 public:
117 ConvertibleToBool (bool res): result_ (res) { /* empty */ }
118 operator bool() const { return result_; }
119 };
120
121 // return a type other than bool but one that is implicitly
122 // convertible to bool to detect incorrect assumptions
124 ++funcalls_;
125 return ConvertibleToBool (arg == val_);
126 }
127
128private:
129 void operator= (EqualityPredicate&);
130 const T &val_;
131};
132
133template <class T>
135
136
138// exercises std::remove() and std::remove_if()
139template <class Iterator, class T, class Predicate>
141 const char *src, const char val, std::size_t nrem,
142 Iterator, NoIterator, const T*,
143 const Predicate*, RemoveTag tag)
144{
145 static const char* const itname = type_name (Iterator (), (T*)0);
146 static const char* const fname = tag.use_predicate ?
147 fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
148
149 // compute the length of the source sequence
150 const std::size_t nsrc = std::strlen (src);
151
152 // construct a sequence of `nsrc' elements to pass to remove
153 T* const xsrc = T::from_char (src, nsrc + 1);
154
155 // construct an element to remove
156 T to_remove;
157 to_remove.data_.val_ = val;
158
159 // construct a predicate object (used with remove_if() only)
160 const Predicate pred (to_remove, 0);
161
162 // construct iterators pointing to the beginning and end
163 // of the source sequence
164 const Iterator first =
165 make_iter (xsrc, xsrc, xsrc + nsrc, Iterator ());
166
167 const Iterator last =
168 make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, Iterator ());
169
170 // zero out predicate counters
171 T::n_total_op_eq_ = 0;
172
173 // call remove() or remove_if()
174 const Iterator end = tag.use_predicate
175 ? std::remove_if (first, last, pred)
176 : std::remove (first, last, to_remove);
177
178 // silence a bogus EDG eccp remark #550-D:
179 // variable "res" was set but never used
181
182 static const int cwidth = sizeof (T);
183
184 // verify that the returned iterator is set as expected
185 bool success = end.cur_ == first.cur_ + (nsrc - nrem);
186 rw_assert (success, 0, line,
187 "line %d: %s<%s>(\"%s\", ..., %#c) == first + %zu, got %zd",
188 __LINE__, fname, itname, src, val,
189 nsrc - nrem, end.cur_ - xsrc);
190
191 // verify that the value to be removed does not appear
192 // anywhere in the range [first, end) : p 25.2.7.2
193 success = true;
194 for (std::size_t i = 0; i != nsrc - nrem && success; ++i) {
195 success = UChar (val) != xsrc [i].data_.val_;
196 rw_assert (success, 0, line,
197 "line %d: %s<%s>(\"%s\", ..., %#c) ==> "
198 "\"%{X=*.*}\"; expected element value %#c",
199 __LINE__, fname, itname, src, val,
200 cwidth, int (nsrc), int (i), xsrc, src [i]);
201 }
202
203
204 // verify that the algorithm is stable: the relative order of the elements
205 // that are not removed remains unchanged : p 25.2.7.4
206 success = true;
207 for (std::size_t i = 1; i < nsrc - nrem && success; ++i) {
208 success = xsrc [i - 1].id_ < xsrc [i].id_;
209 rw_assert (success, 0, line,
210 "line %d: %s<%s>(\"%s\", ..., %#c) ==> \"%{X=#*.*}\"; "
211 "unstable at offset %zu element ids: %d and %d",
212 __LINE__, fname, itname, src, val,
213 cwidth, int (nsrc), int (i - 1), xsrc,
214 i - 1, xsrc [i - 1].id_, xsrc [i].id_);
215 }
216
217
218 // verify that the values of elements in the range [end, last)
219 // are unchanged
220 success = true;
221 for (std::size_t i = nsrc - nrem; i != nsrc && success; ++i) {
222 success = src [i] == xsrc [i].data_.val_;
223 rw_assert (success, 0, line,
224 "line %d: %s<%s>(\"%s\", ..., %#c) ==> "
225 "\"%{X=*.*}\"; expected element value %#c",
226 __LINE__, fname, itname, src, val,
227 cwidth, int (nsrc), int (i), xsrc, val);
228 }
229
230
231 // verify the number of applications of the predicate: p 25.2.7.5
232 if (tag.use_predicate) {
233 rw_assert (pred.funcalls_ == nsrc, 0, line,
234 "line %d: %s<%s>(\"%s\", ..., %#c) called "
235 "Predicate::operator() %zu times, %zu expected",
236 __LINE__, fname, itname, src, val,
237 pred.funcalls_, nsrc);
238 }
239 else {
240 rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
241 "line %d: %s<%s>(\"%s\", ..., %#c) called "
242 "T::operator< %zu times, %zu expected",
243 __LINE__, fname, itname, src, val,
244 T::n_total_op_eq_, nsrc);
245 }
246
247 delete[] xsrc;
248}
249
250
252// exercises std::remove_copy()
253template <class Iterator, class OutputIterator, class Predicate, class T>
255 const char *src, const char val, std::size_t nrem,
256 Iterator it, OutputIterator dummy, const T*,
258{
259 static const char* const itname = type_name (it, (T*)0);
260 static const char* const fname = tag.use_predicate ?
261 fnames_if [tag.fname_inx] : fnames [tag.fname_inx];
262
263 const std::size_t nsrc = std::strlen (src);
264
265 T* const xsrc = T::from_char (src, nsrc);
266 T* const xdst = T::from_char (src, nsrc);
267
268 T to_remove;
269 to_remove.data_.val_ = val;
270
271 const Predicate pred (to_remove, 0);
272
273 const Iterator first = make_iter (xsrc, xsrc, xsrc + nsrc, it);
274 const Iterator last = make_iter (xsrc + nsrc, xsrc, xsrc + nsrc, it);
275 const OutputIterator result = make_iter (xdst, xdst, xdst + nsrc, dummy);
276
277 // zero out predicate counters
278 T::n_total_op_eq_ = 0;
279
280 const OutputIterator end = tag.use_predicate
281 ? std::remove_copy_if (first, last, result, pred)
282 : std::remove_copy (first, last, result, to_remove);
283
284 // silence a bogus EDG eccp remark #550-D:
285 // variable "res" was set but never used
287
288 const int cwidth = sizeof (T);
289
290 // verify that the returned iterator is set as expected p 25.2.7.8
291 bool success = end.cur_ == result.cur_ + (nsrc - nrem);
292 rw_assert (success, 0, line,
293 "line %d: %s<%s>(\"%s\", ..., %#c) == first + %zu, got %zd",
294 __LINE__, fname, itname, src, val, nsrc - nrem, end.cur_ - xsrc);
295
296 // verify that the value to be removed does not appear anywhere
297 // in the range [result, end)
298 success = true;
299 for (std::size_t i = 0; i != nsrc - nrem && success; ++i) {
300 success = UChar (val) != xdst [i].data_.val_;
301 rw_assert (success, 0, line,
302 "line %d: %s<%s>(\"%s\", ..., %#c) ==> "
303 "\"%{X=*.*}\"; expected element value %#c",
304 __LINE__, fname, itname, src, val,
305 cwidth, int (nsrc - nrem), int (i), xdst, src [i]);
306 }
307
308 // verify that the algorithm is stable: the relative order of the elements
309 // that are not removed remains unchanged : p 25.2.7.10
310 success = true;
311 for (std::size_t i = 1; i < nsrc - nrem && success; ++i) {
312 success = xdst [i - 1].id_ < xdst [i].id_;
313 rw_assert (success, 0, line,
314 "line %d: %s<%s>(\"%s\", ..., %#c) ==> \"%{X=#*.*}\"; "
315 "unstable at offset %zu: element ids: %d and %d",
316 __LINE__, fname, itname, src, val,
317 cwidth, int (nsrc - nrem), int (i - 1), xdst,
318 i - 1, xdst [i - 1].id_, xdst [i].id_);
319 }
320
321 // verify the number of applications of the predicate p 25.2.7.9
322 if (tag.use_predicate) {
323 rw_assert (pred.funcalls_ == nsrc, 0, line,
324 "line %d: %s<%s>(\"%s\", ..., %#c) called "
325 "Predicate::operator() %zu times, %zu expected",
326 __LINE__, fname, itname, src, val,
327 pred.funcalls_, nsrc);
328 }
329 else {
330 rw_assert (T::n_total_op_eq_ == nsrc, 0, line,
331 "line %d: %s<%s>(\"%s\", ..., %#c) called "
332 "T::operator< %zu times, %zu expected",
333 __LINE__, fname, itname, src, val,
334 T::n_total_op_eq_, nsrc);
335 }
336
337 delete[] xsrc;
338 delete[] xdst;
339}
340
341
343// exercises all four function templates
344template <class Iterator1, class Iterator2, class T,
345 class Predicate, class Tag>
346void test_remove (Iterator1 it1, Iterator2 it2,
347 const T*, const Predicate* pred, Tag tag)
348{
349 static const char* const it1name = type_name (it1, (T*)0);
350 static const char* const it2name = type_name (it2, (T*)0);
351
352 if (tag.fname_inx) { // remove_copy(), remove_copy_if()
353 rw_info (0, 0, 0,
354 "std::%s (%s, %2$s, %s, %s)",
355 tag.use_predicate ? "remove_copy_if" : "remove_copy",
356 it1name, it2name,
357 tag.use_predicate ? "UnaryPredicate" : "const T&");
358 }
359 else { // remove, remove_if()
360 rw_info (0, 0, 0,
361 "std::%s (%s, %2$s, %s)",
362 tag.use_predicate ? "remove_if" : "remove",
363 it1name,
364 tag.use_predicate ? "UnaryPredicate" : "const T&");
365 }
366
367#define TEST(src, val, nremoved) \
368 test_remove (__LINE__, src, val, nremoved, it1, it2, (T*)0, pred, tag)
369
370 // +---------------------- original sequence
371 // | +------ element to remove
372 // | | +- number of removals
373 // | | |
374 // v v v
375 TEST ("", 'a', 0);
376 TEST ("a", 'a', 1);
377 TEST ("aa", 'a', 2);
378 TEST ("aaa", 'a', 3);
379 TEST ("aaaa", 'a', 4);
380 TEST ("aaaaa", 'a', 5);
381 TEST ("aaaaaa", 'a', 6);
382 TEST ("aaaaaaa", 'a', 7);
383 TEST ("aaaaaaaa", 'a', 8);
384 TEST ("aaaaaaaaa", 'a', 9);
385 TEST ("aaaaaaaaaa", 'a', 10);
386
387 TEST ("b", 'a', 0);
388 TEST ("bb", 'a', 0);
389 TEST ("ba", 'a', 1);
390 TEST ("ab", 'a', 1);
391 TEST ("abc", 'a', 1);
392 TEST ("bac", 'a', 1);
393 TEST ("bca", 'a', 1);
394 TEST ("aba", 'a', 2);
395 TEST ("abab", 'a', 2);
396 TEST ("ababa", 'a', 3);
397 TEST ("bababa", 'a', 3);
398 TEST ("bababab", 'a', 3);
399 TEST ("babababa", 'a', 4);
400 TEST ("baacaadaaeaa",'a', 8);
401}
402
403
405/* extern */ int rw_opt_no_remove; // --no-remove
406/* extern */ int rw_opt_no_remove_if; // --no-remove_if
407/* extern */ int rw_opt_no_remove_copy; // --no-remove_copy
408/* extern */ int rw_opt_no_remove_copy_if; // --no-remove_copy_if
409/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
410/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
411/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
412/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
413/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
414
415
417template <class T, class Predicate, class Tag>
418void test_remove (const T*, const Predicate* pred, Tag tag)
419{
420 rw_info (0, 0, 0,
421 "template <class %s, class T> "
422 "std::%s (%1$s, %1$s, %s)",
423 "ForwardIterator",
424 tag.use_predicate ? "remove_if" : "remove",
425 tag.use_predicate ? "Predicate" : "const T&");
426
427 if (rw_opt_no_fwd_iter) {
428 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
429 }
430 else {
431 test_remove (FwdIter<T>(), NoIterator (), (T*)0, pred, tag);
432 }
433
435 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
436 }
437 else {
438 test_remove (BidirIter<T>(), NoIterator (), (T*)0, pred, tag);
439 }
440
441 if (rw_opt_no_rnd_iter) {
442 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
443 }
444 else {
445 test_remove (RandomAccessIter<T>(), NoIterator (), (T*)0, pred, tag);
446 }
447}
448
449
451template <class T>
452void test_remove (const T*)
453{
454 const RemoveTag remove_tag = { false };
455 const RemoveTag remove_if_tag = { true };
456
457 if (rw_opt_no_remove) {
458 rw_note (0, __FILE__, __LINE__, "std::remove test disabled");
459 }
460 else {
461 const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
462 test_remove((T*)0, pred, remove_tag);
463 }
464
466 rw_note (0, __FILE__, __LINE__, "std::remove_if test disabled");
467 }
468 else {
469 const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 1;
470 test_remove((T*)0, pred, remove_if_tag);
471 }
472}
473
474
476template <class InputIterator, class T, class Predicate, class Tag>
477void test_remove_copy (const InputIterator& iter, const T*,
478 const Predicate* pred, Tag tag)
479{
481 rw_note (0, __FILE__, __LINE__, "OutputIterator test disabled");
482 }
483 else {
484 test_remove (iter, OutputIter<T>(0, 0, 0), (T*)0, pred, tag);
485 }
486
487 if (rw_opt_no_fwd_iter) {
488 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
489 }
490 else {
491 test_remove (iter, FwdIter<T>(), (T*)0, pred, tag);
492 }
493
495 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
496 }
497 else {
498 test_remove (iter, BidirIter<T>(), (T*)0, pred, tag);
499 }
500
501 if (rw_opt_no_rnd_iter) {
502 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
503 }
504 else {
505 test_remove (iter, RandomAccessIter<T>(), (T*)0, pred, tag);
506 }
507}
508
509
511template <class T, class Predicate, class Tag>
512void test_remove_copy (const T*, const Predicate* pred, Tag tag)
513{
514 rw_info (0, 0, 0,
515 "template "
516 "<class InputIterator, class OutputIterator, class T> "
517 "std::%s (InputIterator, InputIterator, "
518 "OutputIterator, %s)",
519 tag.use_predicate ? "remove_copy_if" : "remove_copy",
520 tag.use_predicate ? "Predicate" : "const T&");
521
523 rw_note (0, __FILE__, __LINE__, "InputIterator test disabled");
524 }
525 else {
526 test_remove_copy (InputIter<T>(0, 0, 0), (T*)0, pred, tag);
527 }
528
529 if (rw_opt_no_fwd_iter) {
530 rw_note (0, __FILE__, __LINE__, "ForwardIterator test disabled");
531 }
532 else {
533 test_remove_copy (FwdIter<T>(), (T*)0, pred, tag);
534 }
535
537 rw_note (0, __FILE__, __LINE__, "BidirectionalIterator test disabled");
538 }
539 else {
540 test_remove_copy (BidirIter<T>(), (T*)0, pred, tag);
541 }
542
543 if (rw_opt_no_rnd_iter) {
544 rw_note (0, __FILE__, __LINE__, "RandomAccessIterator test disabled");
545 }
546 else {
548 }
549}
550
551
553template <class T>
554void test_remove_copy (const T* )
555{
556 const RemoveCopyTag remove_copy_tag = { false };
557 const RemoveCopyTag remove_copy_if_tag = { true };
558
560 rw_note (0, __FILE__, __LINE__, "std::remove_copy test disabled");
561 }
562 else {
563 const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 0;
564 test_remove_copy((T*)0, pred, remove_copy_tag);
565 }
566
568 rw_note (0, __FILE__, __LINE__, "std::remove_copy_if test disabled");
569 }
570 else {
571 const EqualityPredicate<T>* const pred = (EqualityPredicate<T>*) 1;
572 test_remove_copy((T*)0, pred, remove_copy_if_tag);
573 }
574}
575
576
578static int
579run_test (int, char*[])
580{
582
584
585 return 0;
586}
587
588
590int main (int argc, char *argv[])
591{
592 return rw_test (argc, argv, __FILE__,
593 "lib.alg.remove",
594 0 /* no comment */, run_test,
595 "|-no-remove# "
596 "|-no-remove_if# "
597 "|-no-remove_copy# "
598 "|-no-remove_copy_if# "
599 "|-no-InputIterator# "
600 "|-no-OutputIterator# "
601 "|-no-ForwardIterator# "
602 "|-no-BidirectionalIterator# "
603 "|-no-RandomAccessIterator#",
613}
#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 last
Definition 17.names.cpp:487
#define Predicate
Definition 17.names.cpp:522
#define val
Definition 17.names.cpp:570
#define OutputIterator
Definition 17.names.cpp:515
#define tag
Definition 17.names.cpp:551
volatile int result
const MyBuffer< char > nsrc[]
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
int rw_opt_no_fwd_iter
unsigned char UChar
const char *const fnames[]
Definition 25.remove.cpp:77
int rw_opt_no_remove_copy_if
int rw_opt_no_rnd_iter
void test_remove(int line, const char *src, const char val, std::size_t nrem, Iterator, NoIterator, const T *, const Predicate *, RemoveTag tag)
const char *const fnames_if[]
Definition 25.remove.cpp:78
int rw_opt_no_bidir_iter
int rw_opt_no_remove
int rw_opt_no_input_iter
int rw_opt_no_remove_copy
#define TEST(src, val, nremoved)
int rw_opt_no_output_iter
void test_remove_copy(const InputIterator &iter, const T *, const Predicate *pred, Tag tag)
int rw_opt_no_remove_if
const char * type_name()
const int end
#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
#define bool
Definition stdbool.h:24
ConvertibleToBool operator()(const T &x, const U &y)
EqualityPredicate(const T &val, int)
static std::size_t funcalls_
const value_type * cur_
static std::size_t funcalls_
Definition 25.find.cpp:62
int use_predicate
Definition 25.remove.cpp:83
int arg
Definition locale.cpp:2806