Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.set.sym.difference.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for set_symmetric_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_symmetric_difference (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
51
52template
54set_symmetric_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
94{
96
97 const char* iter_names [3];
98
99 // ipure virtual
100 virtual UserClass*
102 const UserClass*, UserClass*, UserClass*,
103 const Less*) const = 0;
104};
105
106template <class InputIterator1, class InputIterator2, class OutputIterator>
108{
110 iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
111 iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
112 iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
113 }
114
115 virtual ~SetSymDifference() {}
116
117 virtual UserClass*
118 set_sym_difference (const UserClass *xsrc1, const UserClass *xsrc1_end,
119 const UserClass *xsrc2, const UserClass *xsrc2_end,
120 UserClass *xdst, UserClass *xdst_end,
121 const Less *ppred) const {
122
123 const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
124 const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
125 const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
126 const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
127
128 const OutputIterator result (xdst, xdst, xdst_end);
129
130 const OutputIterator ret = ppred ?
131 std::set_symmetric_difference (first1, last1, first2, last2,
132 result, *ppred)
133 : std::set_symmetric_difference (first1, last1, first2, last2,
134 result);
135
136 // silence EDG eccp 3.7 and prior remark #550-D:
137 // variable was set but never used
138 _RWSTD_UNUSED (ret);
139
140 return ret.cur_;
141 }
142};
143
144
146// exercises set_difference: 25.3.5.5
148 const char *src1,
149 std::size_t nsrc1,
150 const char *src2,
151 std::size_t nsrc2,
152 const char *res,
153 std::size_t ndst,
154 const std::size_t nf,
155 bool predicate,
156 const SetSymDifferenceBase &alg)
157{
158 const char* const it1name = alg.iter_names [0];
159 const char* const it2name = alg.iter_names [1];
160 const char* const outname = alg.iter_names [2];
161 const char* const algname = "set_symmetric_difference";
162 const char* const funname = predicate ? "Less" : 0;
163
164 UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
165 true /* must be sorted */);
166 UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
167 true /* must be sorted */);
168 UserClass* const xdst = new UserClass [ndst];
169
170 // source sequences must be sorted
171 RW_ASSERT (0 == nsrc1 || 0 != xsrc1);
172 RW_ASSERT (0 == nsrc2 || 0 != xsrc2);
173
174 const int max1_id = nsrc1 > 0 ? xsrc1 [nsrc1 - 1].id_ : -1;
175
176 UserClass* const xsrc1_end = xsrc1 + nsrc1;
177 UserClass* const xsrc2_end = xsrc2 + nsrc2;
178 UserClass* const xdst_end = xdst + ndst;
179
180 const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
181
182 const Less pred (0, 0);
183 const Less* const ppred = predicate ? &pred : 0;
184
185 UserClass* xdst_res = alg.set_sym_difference (xsrc1, xsrc1_end,
186 xsrc2, xsrc2_end,
187 xdst, xdst_end, ppred);
188
189 // check the returned value
190 bool success = xdst_res == xdst_end;
191 rw_assert (success, 0, line,
192 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
193 "got res + %td, expected res + %zu",
194 __LINE__, algname, it1name, it2name, outname, predicate,
195 funname, src1, src2, xdst_res - xdst, ndst);
196
197 //quit here to avoid the running out of the array boundaries
198 if (! success) {
199 delete[] xsrc1;
200 delete[] xsrc2;
201 delete[] xdst;
202 return;
203 }
204
205 std::size_t n_ops_lt = ppred ?
207
208 // verify the algorithm correctness
209 std::size_t i = 0;
210 std::size_t n1 = 0;
211 std::size_t n2 = 0;
212 for ( ; i < ndst; i++) {
213 xdst [i].origin_ <= max1_id ? n1++ : n2++;
214 success = xdst [i].data_.val_ == res [i];
215 if (!success)
216 break;
217 }
218
219 // to avoid errors in --trace mode
220 i = i < ndst ? i : ndst - 1;
221
222 static const int cwidth = sizeof (*xdst);
223
224 rw_assert (success, 0, line,
225 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
226 " ==> \"%{X=*.*}\", expected \"%s\"",
227 __LINE__, algname, it1name, it2name, outname, predicate,
228 funname, src1, src2, cwidth, int (ndst), i, xdst, res);
229
230 // verfiy that only elements from first sequence sequence were taken
231 success = n1 == nf;
232 rw_assert (success, 0, line,
233 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
234 " ==> \"%{X=*.*}\" got %zu elements from first sequence and "
235 "%zu from second, expected %zu from first and %zu from second",
236 __LINE__, algname, it1name, it2name, outname, predicate,
237 funname, src1, src2,
238 cwidth, int (ndst), -1, xdst, n1, n2, nf, ndst - nf);
239
240 // verify that the operation is stable: two equal elements
241 // should go in the same order
242 for (i = 1; i < ndst; i++) {
243 if (xdst [i - 1].data_.val_ == xdst [i].data_.val_) {
244 success = xdst [i - 1].origin_ < xdst [i].origin_;
245 if (!success)
246 break;
247 }
248 }
249
250 // to avoid errors in --trace mode
251 if (ndst > 1) {
252 i = i < ndst ? i : ndst - 1;
253
254 rw_assert (success, 0, line,
255 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...)"
256 " ==> \"%{X=*.*}\" not stable : elements %#c==%#c have "
257 "ids %d >= %d ",
258 __LINE__, algname, it1name, it2name, outname, predicate,
259 funname, src1, src2, cwidth, int (ndst), i, xdst,
260 xdst[i - 1].data_.val_, xdst[i].data_.val_,
261 xdst[i - 1].origin_, xdst[i].origin_);
262 }
263
264 // verify the complexity
265 std::size_t n_exp_ops = nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
266 rw_assert (n_ops_lt <= n_exp_ops, 0, line,
267 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
268 "complexity: got %zu, expected no more than %zu",
269 __LINE__, algname, it1name, it2name, outname, predicate,
270 funname, src1, src2, n_ops_lt, n_exp_ops);
271
272 delete[] xsrc1;
273 delete[] xsrc2;
274 delete[] xdst;
275}
276
277
280 bool predicate)
281{
282 const char* const it1name = alg.iter_names [0];
283 const char* const it2name = alg.iter_names [1];
284 const char* const outname = alg.iter_names [2];
285 const char* const algname = "set_symmetric_difference";
286 const char* const funname = predicate ? "Less" : 0;
287
288 rw_info (0, 0, 0,
289 "%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
290 outname, algname, it1name, it2name, predicate, funname);
291
292#define TEST(src1, src2, res, nf) \
293 test_set_sym_difference (__LINE__, src1, sizeof src1 -1, \
294 src2, sizeof src2 - 1, \
295 res, sizeof res - 1, \
296 nf, predicate, alg)
297
298 // +------------------------------ first set
299 // | +--------------------- second set
300 // | | +------------ symmetric difference between them
301 // | | | +-- number of elements from the first
302 // | | | | sequence copied to the result
303 // V V V V
304 TEST ("a", "", "a", 1);
305 TEST ("abcde", "", "abcde", 5);
306 TEST ("", "a", "a", 0);
307 TEST ("", "abcde", "abcde", 0);
308 TEST ("a", "b", "ab", 1);
309 TEST ("b", "a", "ab", 1);
310 TEST ("aa", "aa", "", 0);
311 TEST ("ab", "ab", "", 0);
312 TEST ("aa", "ab", "ab", 1);
313 TEST ("aa", "bb", "aabb", 2);
314 TEST ("ab", "bb", "ab", 1);
315 TEST ("ac", "bb", "abbc", 2);
316 TEST ("ace", "bdf", "abcdef", 3);
317 TEST ("acf", "bdf", "abcd", 2);
318 TEST ("ade", "bdf", "abef", 2);
319 TEST ("bce", "bdf", "cdef", 2);
320 TEST ("aacee", "aacee", "", 0);
321 TEST ("aacee", "aaace", "ae", 1);
322 TEST ("aacee", "aaaae", "aace", 2);
323 TEST ("aacee", "aaaaa", "aaacee", 3);
324 TEST ("aacee", "aaabd", "abcdee", 3);
325 TEST ("aacee", "aabee", "bc", 1);
326 TEST ("aaaaa", "aaaaa", "", 0);
327 TEST ("aaaaa", "aaaa", "a", 1);
328 TEST ("aaaaa", "aaa", "aa", 2);
329 TEST ("aaaaa", "aa", "aaa", 3);
330 TEST ("aaaaa", "a", "aaaa", 4);
331}
332
333
335/* extern */ int rw_opt_no_predicate; // --no-predicate
336/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
337/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
338/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
339/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
340/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
341
342
344template <class InputIterator1, class InputIterator2, class OutputIterator>
345void gen_set_sym_difference_test (const InputIterator1&,
346 const InputIterator2&,
347 const OutputIterator&,
348 bool predicate)
349{
350 const SetSymDifference<
351 InputIterator1, InputIterator2, OutputIterator> alg;
352
354}
355
356
358template <class InputIterator1, class InputIterator2>
359void gen_set_sym_difference_test (const InputIterator1 &it1,
360 const InputIterator2 &it2,
361 bool predicate)
362{
363 if (0 == rw_opt_no_output_iter)
365 it1, it2, OutputIter<UserClass>(0, 0, 0), predicate);
366 if (0 == rw_opt_no_fwd_iter)
368 it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
369 if (0 == rw_opt_no_bidir_iter)
371 it1, it2, BidirIter<UserClass>(0, 0, 0), predicate);
372 if (0 == rw_opt_no_rnd_iter)
374 it1, it2, RandomAccessIter<UserClass>(0, 0, 0), predicate);
375}
376
377template <class InputIterator1>
378void gen_set_sym_difference_test (const InputIterator1 &it1,
379 bool predicate)
380{
381 if (0 == rw_opt_no_input_iter)
383 it1, InputIter<UserClass>(0, 0, 0), predicate);
384 if (0 == rw_opt_no_fwd_iter)
386 it1, ConstFwdIter<UserClass>(0, 0, 0), predicate);
387 if (0 == rw_opt_no_bidir_iter)
389 it1, ConstBidirIter<UserClass>(0, 0, 0), predicate);
390 if (0 == rw_opt_no_rnd_iter)
393}
394
395// generates a specialization of the set_union test for each of the required
396// iterator categopries
398{
399 rw_info (0, 0, 0,
400 "template <class %s, class %s, class %s%{?}, class %s%{;}> %3$s "
401 "set_symmetric_difference (%1$s, %1$s, %2$s, %2$s, "
402 "%3$s%{?}, %s%{;})",
403 "InputIterator1", "InputIterator2", "OutputIterator",
404 predicate, "Compare", predicate, "Compare");
405
407 rw_note (0, 0, 0, "OutputIterator test disabled");
408
410 rw_note (0, 0, 0, "InputIterator test disabled");
411 else
413
415 rw_note (0, 0, 0, "ForwardIterator test disabled");
416 else
418 predicate);
419
421 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
422 else
424 predicate);
425
427 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
428 else
431}
432
433
435static int run_test (int, char*[])
436{
438 rw_note (0, 0, 0, "predicate test disabled");
439
440 const int niters = rw_opt_no_predicate ? 1 : 2;
441
443 for (int i = 0; i != niters; ++i) {
445 }
446
447 return 0;
448}
449
450
452int main (int argc, char *argv[])
453{
454 return rw_test (argc, argv, __FILE__,
455 "lib.set.symmetric.difference",
456 0 /* no comment */, run_test,
457 "|-no-predicate#"
458 "|-no-InputIterator# "
459 "|-no-OutputIterator# "
460 "|-no-ForwardIterator# "
461 "|-no-BidirectionalIterator# "
462 "|-no-RandomAccessIterator#",
469}
#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)
#define TEST(src1, src2, res, nf)
int rw_opt_no_fwd_iter
void test_set_sym_difference(int line, const char *src1, std::size_t nsrc1, const char *src2, std::size_t nsrc2, const char *res, std::size_t ndst, const std::size_t nf, bool predicate, const SetSymDifferenceBase &alg)
int rw_opt_no_rnd_iter
void gen_set_sym_difference_test(const InputIterator1 &, const InputIterator2 &, const OutputIterator &, bool predicate)
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
virtual UserClass * set_sym_difference(const UserClass *, const UserClass *, const UserClass *, const UserClass *, UserClass *, UserClass *, const Less *) const =0
virtual UserClass * set_sym_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)