Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.set.difference.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for set_difference
30#include <cstddef> // for size_t
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
46set_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
51
52template
54set_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
60
61#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
62
63} // namespace std
64
65
67struct Less
68{
69 static std::size_t funcalls_;
70
71 // dummy arguments provided to prevent the class from being
72 // default constructible and implicit conversion from int
73 Less (int /* dummy */, int /* dummy */) {
74 funcalls_ = 0;
75 }
76
77 // return a type other than bool but one that is implicitly
78 // convertible to bool to detect incorrect assumptions
80 const UserClass &y) /* non-const */ {
81 ++funcalls_;
82 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
83 }
84
85private:
86 void operator= (Less&); // not assignable
87};
88
89std::size_t Less::funcalls_;
90
91
93// ordinary (non-template) base to minimize code bloat
95{
96 virtual ~SetDifferenceBase() {}
97
98 const char* iter_names [3];
99
100 // pure virtual
101 virtual UserClass*
103 const UserClass*, UserClass*, UserClass*,
104 const Less*) const = 0;
105};
106
107template <class InputIterator1, class InputIterator2, class OutputIterator>
109{
111 iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
112 iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
113 iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
114 }
115
116 virtual UserClass*
117 set_difference (const UserClass *xsrc1, const UserClass *xsrc1_end,
118 const UserClass *xsrc2, const UserClass *xsrc2_end,
119 UserClass *xdst, UserClass *xdst_end,
120 const Less *ppred) const {
121
122 const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
123 const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
124 const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
125 const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
126
127 const OutputIterator result (xdst, xdst, xdst_end);
128
129 const OutputIterator ret = ppred ?
130 std::set_difference (first1, last1, first2, last2, result, *ppred)
131 : std::set_difference (first1, last1, first2, last2, result);
132
133 // silence EDG eccp 3.7 and prior remark #550-D:
134 // variable was set but never used
135 _RWSTD_UNUSED (ret);
136
137 return ret.cur_;
138 }
139};
140
141
143// exercises set_difference: 25.3.5.4
145 const char *src1,
146 std::size_t nsrc1,
147 const char *src2,
148 std::size_t nsrc2,
149 const char *res,
150 std::size_t ndst,
151 bool predicate,
152 const SetDifferenceBase &alg)
153{
154 const char* const it1name = alg.iter_names [0];
155 const char* const it2name = alg.iter_names [1];
156 const char* const outname = alg.iter_names [2];
157 const char* const fname = "set_difference";
158 const char* const funname = predicate ? "Less" : 0;
159
160 UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
161 true /* must be sorted */);
162 UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
163 true /* must be sorted */);
164
165 // assert that the sequences have been successfully created
166 RW_ASSERT (0 == nsrc1 || xsrc1);
167 RW_ASSERT (0 == nsrc2 || xsrc2);
168
169 UserClass* const xdst = new UserClass [ndst];
170
171 const int max1_id = nsrc1 > 0 ? xsrc1[nsrc1 - 1].id_ : -1;
172
173 UserClass* const xsrc1_end = xsrc1 + nsrc1;
174 UserClass* const xsrc2_end = xsrc2 + nsrc2;
175 UserClass* const xdst_end = xdst + ndst;
176
177 const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
178
179 const Less pred (0, 0);
180 const Less* const ppred = predicate ? &pred : 0;
181
182 UserClass* xdst_res = alg.set_difference (xsrc1, xsrc1_end,
183 xsrc2, xsrc2_end,
184 xdst, xdst_end, ppred);
185
186 // check the returned value
187 bool success = xdst_res == xdst_end;
188 rw_assert (success, 0, line,
189 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
190 "got res + %td, expected res + %zu",
191 __LINE__, fname, it1name, it2name, outname, predicate,
192 funname, src1, src2, xdst_res - xdst, ndst);
193
194 // quit here to avoid the running out of the array boundaries
195 if (!success) {
196 delete[] xsrc1;
197 delete[] xsrc2;
198 delete[] xdst;
199 return;
200 }
201
202 const std::size_t n_ops_lt = ppred ?
204
205 // verify the algorithm correctness
206 std::size_t i = 0;
207 std::size_t n1 = 0;
208 std::size_t n2 = 0;
209 for ( ; i < ndst; ++i) {
210 xdst[i].origin_ <= max1_id ? n1++ : n2++;
211 success = xdst[i].data_.val_ == res[i];
212 if (!success)
213 break;
214 }
215
216 // to avoid errors in --trace mode
217 i = i < ndst ? i : ndst - 1;
218
219 static const int cwidth = sizeof (*xdst);
220
221 rw_assert (success, 0, line,
222 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
223 " ==> \"%{X=*.*}\", expected \"%s\"",
224 __LINE__, fname, it1name, it2name, outname, predicate,
225 funname, src1, src2, cwidth, int (ndst), i, xdst, res);
226
227 // verfiy that only elements from first sequence sequence were taken
228 success = n1 == ndst;
229 rw_assert (success, 0, line,
230 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
231 " ==> \"%{X=*.*}\" got %zu elements from first sequence and "
232 "%zu from second, expected %zu from first and 0 from second",
233 __LINE__, fname, it1name, it2name, outname, predicate, funname,
234 src1, src2, cwidth, int (ndst), -1, xdst, n1, n2, ndst);
235
236 // verify that the operation is stable : two equal elements
237 // should go in the same order
238 for (i = 1; i < ndst; i++) {
239 success = xdst[i - 1].origin_ < xdst[i].origin_;
240 if (!success)
241 break;
242 }
243
244 // to avoid errors in --trace mode
245 if (ndst > 1) {
246 i = i < ndst ? i : ndst - 1;
247
248 rw_assert (success, 0, line,
249 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
250 " ==> \"%{X=*.*}\" not stable : elements %#c==%#c have "
251 "ids %d >= %d ",
252 __LINE__, fname, it1name, it2name, outname, predicate,
253 funname, src1, src2, cwidth, int (ndst), i, xdst,
254 xdst[i - 1].data_.val_, xdst[i].data_.val_,
255 xdst[i - 1].origin_, xdst[i].origin_);
256 }
257
258 // verify the complexity
259 const std::size_t n_exp_ops =
260 nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
261
262 rw_assert (n_ops_lt <= n_exp_ops, 0, line,
263 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
264 "complexity: got %zu, expected no more than %zu",
265 __LINE__, fname, it1name, it2name, outname, predicate, funname,
266 src1, src2, n_ops_lt, n_exp_ops);
267
268 delete[] xsrc1;
269 delete[] xsrc2;
270 delete[] xdst;
271}
272
273
276 bool predicate)
277{
278 const char* const it1name = alg.iter_names [0];
279 const char* const it2name = alg.iter_names [1];
280 const char* const outname = alg.iter_names [2];
281 const char* const fname = "set_difference";
282 const char* const funname = predicate ? "Less" : 0;
283
284 rw_info (0, 0, 0,
285 "%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
286 outname, fname, it1name, it2name, predicate, funname);
287
288#define TEST(src1, src2, res) \
289 test_set_difference (__LINE__, src1, sizeof src1 - 1, \
290 src2, sizeof src2 - 1, res, sizeof res - 1, \
291 predicate, alg)
292
293 // +-------------------- first set
294 // | +----------- second set
295 // | | +-- difference
296 // | | |
297 // V V V
298 TEST ("a", "", "a");
299 TEST ("abcde", "", "abcde");
300 TEST ("", "a", "");
301 TEST ("", "abcde", "");
302 TEST ("a", "b", "a");
303 TEST ("b", "a", "b");
304 TEST ("aa", "aa", "");
305 TEST ("ab", "ab", "");
306 TEST ("aa", "ab", "a");
307 TEST ("aa", "bb", "aa");
308 TEST ("ab", "bb", "a");
309 TEST ("ac", "bb", "ac");
310 TEST ("ace", "bdf", "ace");
311 TEST ("acf", "bdf", "ac");
312 TEST ("ade", "bdf", "ae");
313 TEST ("bce", "bdf", "ce");
314 TEST ("aacee", "aacee", "");
315 TEST ("aacee", "aaace", "e");
316 TEST ("aacee", "aaaae", "ce");
317 TEST ("aacee", "aaaaa", "cee");
318 TEST ("aacee", "aaabd", "cee");
319 TEST ("aacee", "aabee", "c");
320 TEST ("aaaaa", "aaaaa", "");
321 TEST ("aaaaa", "aaaa", "a");
322 TEST ("aaaaa", "aaa", "aa");
323 TEST ("aaaaa", "aa", "aaa");
324 TEST ("aaaaa", "a", "aaaa");
325 TEST ("acegi", "bdfhj", "acegi");
326 TEST ("bdfhj", "acegi", "bdfhj");
327}
328
329
331/* extern */ int rw_opt_no_predicate; // --no-predicate
332/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
333/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
334/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
335/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
336/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
337
338
340template <class InputIterator1, class InputIterator2, class OutputIterator>
341void gen_set_difference_test (const InputIterator1&,
342 const InputIterator2&,
343 const OutputIterator&,
344 bool predicate)
345{
347
349}
350
351
353template <class InputIterator1, class InputIterator2>
354void gen_set_difference_test (const InputIterator1 &it1,
355 const InputIterator2 &it2,
356 bool predicate)
357{
358 if (0 == rw_opt_no_output_iter)
360 it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
361 if (0 == rw_opt_no_fwd_iter)
363 it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
364 if (0 == rw_opt_no_bidir_iter)
366 it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
367 if (0 == rw_opt_no_rnd_iter)
369 it1, it2, RandomAccessIter<UserClass>(0, 0, 0), predicate);
370}
371
372template <class InputIterator1>
373void gen_set_difference_test (const InputIterator1 &it1,
374 bool predicate)
375{
376 if (0 == rw_opt_no_input_iter)
378 it1, InputIter<UserClass>(0, 0, 0), predicate);
379 if (0 == rw_opt_no_fwd_iter)
381 it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
382 if (0 == rw_opt_no_bidir_iter)
384 it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
385 if (0 == rw_opt_no_rnd_iter)
388}
389
390// generates a specialization of the set_union test for each of the required
391// iterator categopries
393{
394 rw_info (0, 0, 0,
395 "template <class %s, class %s, class %s%{?}, class %s%{;}> %3$s "
396 "set_difference (%1$s, %1$s, %2$s, %2$s, %3$s%{?}, %s%{;})",
397 "InputIterator1", "InputIterator2", "OutputIterator",
398 predicate, "Compare", predicate, "Compare");
399
401 rw_note (0, 0, 0, "OutputIterator test disabled");
402
404 rw_note (0, 0, 0, "InputIterator test disabled");
405 else
407
409 rw_note (0, 0, 0, "ForwardIterator test disabled");
410 else
412
414 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
415 else
417
419 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
420 else
423}
424
425
427static int
428run_test (int, char*[])
429{
431 rw_note (0, 0, 0, "predicate test disabled");
432
433 const int niters = rw_opt_no_predicate ? 1 : 2;
434
436 for (int i = 0; i != niters; ++i) {
438 }
439
440 return 0;
441}
442
443
445int main (int argc, char *argv[])
446{
447 return rw_test (argc, argv, __FILE__,
448 "lib.set.difference",
449 0 /* no comment */, run_test,
450 "|-no-predicate#"
451 "|-no-InputIterator# "
452 "|-no-OutputIterator# "
453 "|-no-ForwardIterator# "
454 "|-no-BidirectionalIterator# "
455 "|-no-RandomAccessIterator#",
462}
#define i
Definition 17.names.cpp:126
#define y
Definition 17.names.cpp:141
#define line
Definition 17.names.cpp:490
#define res
Definition 17.names.cpp:531
#define n2
Definition 17.names.cpp:263
#define x
Definition 17.names.cpp:140
#define n1
Definition 17.names.cpp:237
#define OutputIterator
Definition 17.names.cpp:515
volatile int result
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
void test_set_difference(int line, const char *src1, std::size_t nsrc1, const char *src2, std::size_t nsrc2, const char *res, std::size_t ndst, bool predicate, const SetDifferenceBase &alg)
void gen_set_difference_test(const InputIterator1 &, const InputIterator2 &, const OutputIterator &, bool predicate)
int rw_opt_no_fwd_iter
#define TEST(src1, src2, res)
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_input_iter
int rw_opt_no_predicate
int rw_opt_no_output_iter
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
_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 RW_ASSERT(expr)
conv_to_bool operator()(const T &x, const T &y)
Definition 25.heap.cpp:114
static std::size_t funcalls_
Definition 25.heap.cpp:104
Less(int, int)
virtual UserClass * set_difference(const UserClass *, const UserClass *, const UserClass *, const UserClass *, UserClass *, UserClass *, const Less *) const =0
const char * iter_names[3]
virtual UserClass * set_difference(const UserClass *xsrc1, const UserClass *xsrc1_end, const UserClass *xsrc2, const UserClass *xsrc2_end, UserClass *xdst, UserClass *xdst_end, const Less *ppred) const
int origin_
Definition rw_value.h:82
const int id_
Definition rw_value.h:81
static UserClass from_char(char c)
Definition rw_value.h:221
UserData data_
Definition rw_value.h:79
static _RWSTD_SIZE_T n_total_op_lt_
Definition rw_value.h:133
int val_
Definition rw_value.h:39
static conv_to_bool make(bool val)