Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.set.union.cpp
Go to the documentation of this file.
1
29#include <algorithm> // for set_union
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#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
41
42template
44set_union (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
49
50template
52set_union (InputIter<lt_comp<assign<base<cpy_ctor> > > >,
58
59#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
60
61} // namespace std
62
63
65struct Less
66{
67 static std::size_t funcalls_;
68
69 // dummy arguments provided to prevent the class from being
70 // default constructible and implicit conversion from int
71 Less (int /* dummy */, int /* dummy */) {
72 funcalls_ = 0;
73 }
74
75 // return a type other than bool but one that is implicitly
76 // convertible to bool to detect incorrect assumptions
78 const UserClass &y) /* non-const */ {
79 ++funcalls_;
80 return conv_to_bool::make (x.data_.val_ < y.data_.val_);
81 }
82
83private:
84 void operator= (Less&); // not assignable
85};
86
87std::size_t Less::funcalls_;
88
89
91// ordinary (non-template) base to minimize code bloat
93{
94 virtual ~SetUnionBase() { /* no-op */ }
95
96 const char* iter_names [3];
97
98 // pure virtual, must be overridden
99 virtual UserClass*
100 set_union (const UserClass*, const UserClass*, const UserClass*,
101 const UserClass*, UserClass*, UserClass*,
102 const Less*) const = 0;
103};
104
105template <class InputIterator1, class InputIterator2, class OutputIterator>
107{
109 iter_names [0] = type_name (InputIterator1 (0, 0, 0), (UserClass*)0);
110 iter_names [1] = type_name (InputIterator2 (0, 0, 0), (UserClass*)0);
111 iter_names [2] = type_name (OutputIterator (0, 0, 0), (UserClass*)0);
112 }
113
114 virtual UserClass*
115 set_union (const UserClass *xsrc1, const UserClass *xsrc1_end,
116 const UserClass *xsrc2, const UserClass *xsrc2_end,
117 UserClass *xdst, UserClass *xdst_end,
118 const Less *ppred) const {
119
120 const InputIterator1 first1 (xsrc1, xsrc1, xsrc1_end);
121 const InputIterator1 last1 (xsrc1_end, xsrc1, xsrc1_end);
122 const InputIterator2 first2 (xsrc2, xsrc2, xsrc2_end);
123 const InputIterator2 last2 (xsrc2_end, xsrc2, xsrc2_end);
124
125 const OutputIterator result (xdst, xdst, xdst_end);
126
127 const OutputIterator ret = ppred ?
128 std::set_union (first1, last1, first2, last2, result, *ppred)
129 : std::set_union (first1, last1, first2, last2, result);
130
131 // silence EDG eccp 3.7 and prior remark #550-D:
132 // variable was set but never used
133 _RWSTD_UNUSED (ret);
134
135 return ret.cur_;
136 }
137};
138
139
142 const char *src1,
143 std::size_t nsrc1,
144 const char *src2,
145 std::size_t nsrc2,
146 const char *res,
147 std::size_t ndst,
148 bool predicate,
149 const SetUnionBase &alg)
150{
151 const char* const it1name = alg.iter_names [0];
152 const char* const it2name = alg.iter_names [1];
153 const char* const outname = alg.iter_names [2];
154 const char* const fname = "set_union";
155 const char* const funname = predicate ? "Less" : 0;
156
157 UserClass* const xsrc1 = UserClass::from_char (src1, nsrc1,
158 true /* must be sorted */);
159 UserClass* const xsrc2 = UserClass::from_char (src2, nsrc2,
160 true /* must be sorted */);
161 // assert that the sequences have been successfully created
162 RW_ASSERT (0 == nsrc1 || xsrc1);
163 RW_ASSERT (0 == nsrc2 || xsrc2);
164
165 UserClass* const xdst = new UserClass [ndst];
166
167 const int max1_id = nsrc1 > 0 ? xsrc1 [nsrc1 - 1].id_ : -1;
168
169 UserClass* const xsrc1_end = xsrc1 + nsrc1;
170 UserClass* const xsrc2_end = xsrc2 + nsrc2;
171 UserClass* const xdst_end = xdst + ndst;
172
173 const std::size_t last_n_op_lt = UserClass::n_total_op_lt_;
174
175 const Less pred (0, 0);
176 const Less* const ppred = predicate ? &pred : 0;
177
178 const UserClass* const xdst_res =
179 alg.set_union (xsrc1, xsrc1_end, xsrc2, xsrc2_end,
180 xdst, xdst_end, ppred);
181
182 // check the returned value
183 bool success = xdst_res == xdst_end;
184 rw_assert (success, 0, line,
185 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
186 "got res + %td, expected res + %zu",
187 __LINE__, fname, it1name, it2name, outname, predicate,
188 funname, src1, src2, xdst_res - xdst, ndst);
189
190 //quit here to avoid the running out of the array boundaries
191 if (! success) {
192 delete[] xsrc1;
193 delete[] xsrc2;
194 delete[] xdst;
195 return;
196 }
197
198 const std::size_t n_ops_lt = ppred ?
200
201 // check the algorithm correctness
202 std::size_t i = 0;
203 std::size_t n1 = 0;
204 std::size_t n2 = 0;
205 for ( ; i < ndst; i++) {
206 xdst[i].origin_ <= max1_id ? n1++ : n2++;
207 success = xdst[i].data_.val_ == res[i];
208 if (!success)
209 break;
210 }
211
212 // to avoid errors in --trace mode
213 i = i < ndst ? i : ndst - 1;
214
215 static const int cwidth = sizeof (*xdst);
216
217 rw_assert (success, 0, line,
218 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
219 " ==> \"%{X=*.*}\", expected \"%s\"",
220 __LINE__, fname, it1name, it2name, outname, predicate,
221 funname, src1, src2, cwidth, int (ndst), i, xdst, res);
222
223 // check that the operation is stable : for two equal elements
224 // one from the first sequence should be taken
225 success = n1 == nsrc1;
226 rw_assert (success, 0, line,
227 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
228 " ==> \"%{X=*.*}\" got %zu elements from first sequence and "
229 "%zu from second, expected %zu from first and %zu from second",
230 __LINE__, fname, it1name, it2name, outname, predicate, funname,
231 src1, src2, cwidth, int (ndst), -1, xdst,
232 n1, n2, nsrc1, ndst - nsrc1);
233
234 // check the complexity
235 const std::size_t n_exp_ops =
236 nsrc1 + nsrc2 > 0 ? 2 * (nsrc1 + nsrc2) - 1 : 0;
237
238 rw_assert (n_ops_lt <= n_exp_ops, 0, line,
239 "line %d: %s<%s, %s, %s%{?}, %s%{;}> (\"%s\", \"%s\", ...) "
240 "complexity: got %zu, expected no more than %zu",
241 __LINE__, fname, it1name, it2name, outname, predicate, funname,
242 src1, src2, n_ops_lt, n_exp_ops);
243
244 delete[] xsrc1;
245 delete[] xsrc2;
246 delete[] xdst;
247}
248
249
251void test_set_union (const SetUnionBase &alg,
252 bool predicate)
253{
254 const char* const it1name = alg.iter_names [0];
255 const char* const it2name = alg.iter_names [1];
256 const char* const outname = alg.iter_names [2];
257 const char* const fname = "set_union";
258 const char* const funname = predicate ? "Less" : 0;
259
260 rw_info (0, 0, 0,
261 "%s std::%s(%s, %3$s, %s, %4$s, %1$s%{?}, %s%{;})",
262 outname, fname, it1name, it2name, predicate, funname);
263
264#define TEST(src1, src2, res) \
265 test_set_union (__LINE__, src1, sizeof src1 - 1, \
266 src2, sizeof src2 - 1, \
267 res, sizeof res - 1, \
268 predicate, alg)
269
270 TEST ("a", "", "a");
271 TEST ("abcde", "", "abcde");
272
273 TEST ("", "a", "a");
274 TEST ("", "abcde", "abcde");
275
276 TEST ("a", "b", "ab");
277 TEST ("b", "a", "ab");
278
279 TEST ("aa", "aa", "aa");
280 TEST ("ab", "ab", "ab");
281
282 TEST ("aa", "ab", "aab");
283 TEST ("aa", "bb", "aabb");
284 TEST ("ab", "bb", "abb");
285 TEST ("ac", "bb", "abbc");
286
287 TEST ("ace", "bdf", "abcdef");
288 TEST ("acf", "bdf", "abcdf");
289 TEST ("ade", "bdf", "abdef");
290 TEST ("bce", "bdf", "bcdef");
291
292 TEST ("abcde", "fghij", "abcdefghij");
293 TEST ("aacde", "ffhij", "aacdeffhij");
294 TEST ("abbde", "fggij", "abbdefggij");
295 TEST ("abcce", "fghhj", "abccefghhj");
296 TEST ("abcdd", "fghii", "abcddfghii");
297
298 TEST ("aacee", "aacee", "aacee");
299 TEST ("aacee", "aaace", "aaacee");
300 TEST ("aacee", "aaaae", "aaaacee");
301 TEST ("aacee", "aaaaa", "aaaaacee");
302 TEST ("aacee", "aaaab", "aaaabcee");
303 TEST ("aacee", "aaabd", "aaabcdee");
304 TEST ("aacee", "aabee", "aabcee");
305}
306
307
309/* extern */ int rw_opt_no_predicate; // --no-predicate
310/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
311/* extern */ int rw_opt_no_output_iter; // --no-OutputIterator
312/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
313/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
314/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
315
316
318template <class InputIterator1, class InputIterator2, class OutputIterator>
319void gen_set_union_test (const InputIterator1&,
320 const InputIterator2&,
321 const OutputIterator&,
322 bool predicate)
323{
325
327}
328
329
331template <class InputIterator1, class InputIterator2>
332void gen_set_union_test (const InputIterator1 &it1,
333 const InputIterator2 &it2,
334 bool predicate)
335{
336 if (0 == rw_opt_no_output_iter)
337 gen_set_union_test (it1, it2, OutputIter<UserClass>(0, 0, 0),
338 predicate);
339 if (0 == rw_opt_no_fwd_iter)
340 gen_set_union_test (it1, it2, FwdIter<UserClass>(0, 0, 0), predicate);
341 if (0 == rw_opt_no_bidir_iter)
343 if (0 == rw_opt_no_rnd_iter)
345 predicate);
346}
347
348template <class InputIterator1>
349void gen_set_union_test (const InputIterator1 &it1,
350 bool predicate)
351{
352 if (0 == rw_opt_no_input_iter)
354 if (0 == rw_opt_no_fwd_iter)
356 if (0 == rw_opt_no_bidir_iter)
358 if (0 == rw_opt_no_rnd_iter)
360 predicate);
361}
362
363// generates a specialization of the set_union test for each of the required
364// iterator categories
366{
367 rw_info (0, 0, 0,
368 "template <class %s, class %s, class %s%{?}, class %s%{;}> "
369 "%3$s set_union(%1$s, %1$s, %2$s, %2$s, %3$s%{?}, %s%{;})",
370 "InputIterator1", "InputIterator2", "OutputIterator",
371 predicate, "Compare", predicate, "Compare");
372
374 rw_note (0, 0, 0, "OutputIterator test disabled");
375
377 rw_note (0, 0, 0, "InputIterator test disabled");
378 else
380
382 rw_note (0, 0, 0, "ForwardIterator test disabled");
383 else
385
387 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
388 else
390
392 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
393 else
395 predicate);
396}
397
398
400static int run_test (int, char*[])
401{
403 rw_note (0, 0, 0, "predicate test disabled");
404
405 const int niters = rw_opt_no_predicate ? 1 : 2;
406
408 for (int i = 0; i != niters; ++i) {
409 gen_set_union_test (1 == i);
410 }
411
412 return 0;
413}
414
415
417int main (int argc, char *argv[])
418{
419 return rw_test (argc, argv, __FILE__,
420 "lib.set.union",
421 0 /* no comment */,
422 run_test,
423 "|-no-predicate#"
424 "|-no-InputIterator# "
425 "|-no-OutputIterator# "
426 "|-no-ForwardIterator# "
427 "|-no-BidirectionalIterator# "
428 "|-no-RandomAccessIterator#",
435}
#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)
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
void gen_set_union_test(const InputIterator1 &, const InputIterator2 &, const OutputIterator &, bool predicate)
int rw_opt_no_output_iter
void test_set_union(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 SetUnionBase &alg)
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)
const char * iter_names[3]
virtual UserClass * set_union(const UserClass *, const UserClass *, const UserClass *, const UserClass *, UserClass *, UserClass *, const Less *) const =0
virtual ~SetUnionBase()
virtual UserClass * set_union(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)