Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.equal.range.cpp
Go to the documentation of this file.
1
29#include <rw/_config.h>
30
31#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
32 // disable implicit inclusion to work around a limitation
33 // of IBM VisualAge 5.0 (see PR #26959)
34# define _RWSTD_NO_IMPLICIT_INCLUSION
35#endif
36
37#include <algorithm> // for equal_range()
38#include <cstring> // for strlen()
39
40#include <rw_alg_test.h> // for iterators
41#include <rw_value.h> // for UserClass
42#include <rw_driver.h> // for rw_test(), ...
43
44
47
48#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
49
50template
51pair <FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
53equal_range (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
55 const lt_comp<assign<base<cpy_ctor> > >&);
56
57template
58pair <FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
60equal_range (FwdIter<lt_comp<assign<base<cpy_ctor> > > >,
62 const lt_comp<assign<base<cpy_ctor> > >&,
64
65#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
66
67} // namespace std
68
69
71// distinct and not Less-Than-Comparable with class T (except as
72// defined below) to detect unwarranted assumptions made by the
73// implementation of the algorithms
74struct Y
75{
77
78 // not Default-Constructible
79 Y (char val, int /*dummy */): xval_ () {
80 typedef unsigned char UChar;
81 xval_.data_.val_ = int (UChar (val));
82 }
83
84 // CopyConstructible
85 Y (const Y &rhs): xval_ (rhs.xval_) { }
86
87private:
88
89 void operator=(Y&); // not Assignable
90};
91
92
94operator< (const UserClass &lhs, const Y &rhs)
95{
96 return conv_to_bool::make (lhs < rhs.xval_);
97}
98
100operator< (const Y &lhs, const UserClass &rhs)
101{
102 return conv_to_bool::make (lhs.xval_ < rhs);
103}
104
105// predicate used as the Compare argument to upper_bound()
106struct LessThan
107{
108 static std::size_t funcalls_;
109
110 LessThan (int /* dummy */, int /* dummy */) {
111 funcalls_ = 0;
112 }
113
114 // return a type other than bool but one that is implicitly
115 // convertible to bool to detect incorrect assumptions
117 ++funcalls_;
118 return conv_to_bool::make (lhs < rhs.xval_);
119 }
120
122 ++funcalls_;
123 return conv_to_bool::make (lhs.xval_ < rhs);
124 }
125
126private:
127 void operator= (LessThan&); // not assignable
128};
129
130std::size_t LessThan::funcalls_;
131
132
134template <class T, class ForwardIterator>
136 const char *src_str,
137 char val_char,
138 std::size_t result_loff,
139 std::size_t result_uoff,
140 std::size_t ncomp,
141 const ForwardIterator &it,
142 const T*,
143 bool predicate)
144{
145 RW_ASSERT (0 != src_str);
146
147 const char* const tname = "UserClass";
148 const char* const itname = type_name (it, (T*)0);
149 const char* const funname = predicate ? "LessThan" : "operator<()";
150
151 const std::size_t nsrc = std::strlen (src_str);
152 T* const xsrc = T::from_char (src_str, nsrc + 1);
153 T* const xsrc_end = xsrc + nsrc;
154
155 if (nsrc < result_uoff)
156 result_uoff = nsrc;
157
158 // construct the source range to pass to the algorithm
159 const ForwardIterator first = make_iter (xsrc, xsrc, xsrc_end, it);
160 const ForwardIterator last = make_iter (xsrc_end, xsrc, xsrc_end, it);
161
162 // construct the object to pass to the algorithm
163 // the type of the object is distinct from the iterator's value_type
164 // to detect unwarranted assumptions made by the implementation of
165 // the algorithm
166 const Y value (val_char, 0 /* dummy */);
167
168 // construct the Compare function object to pass to the algorithm
169 // when `predicate' is true
170 const LessThan comp (0, 0 /* dummy arguments */);
171
172 // reset the counter of invocations of T::operator<()
173 T::n_total_op_lt_ = 0;
174
175 // invoke the appropriate form of the algorithm, storing
176 // the resturned value
177 const std::pair <ForwardIterator, ForwardIterator> result = predicate
178 ? std::equal_range (first, last, value, comp)
179 : std::equal_range (first, last, value);
180
181 // silence bogus EDG eccp 3.6 remark #550-D:
182 // variable was set but never used
184
185 // verify correctness
186 const std::size_t loff = std::size_t (result.first.cur_ - xsrc);
187 const std::size_t uoff = std::size_t (result.second.cur_ - xsrc);
188
189 rw_assert (loff == result_loff && uoff == result_uoff, 0, line,
190 "equal_range <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
191 "== first + { %zu, %zu }, got first + { %zu, %zu }",
192 itname, tname, predicate, funname, src_str, val_char,
193 loff, uoff, result_loff, result_uoff);
194
195 // verify complexity
196 const std::size_t n_ops = predicate
197 ? LessThan::funcalls_ : T::n_total_op_lt_;
198
199 rw_assert (n_ops <= ncomp, 0, line,
200 "equal_range <%s, const %s&%{?}, %s%{;}> (\"%s\", %#c, ...) "
201 "complexity: invoked %4$s at most %zu times, got %zu",
202 itname, tname, predicate, funname, src_str, val_char,
203 ncomp, n_ops);
204
205 delete[] xsrc;
206}
207
208
210template <class T, class ForwardIterator>
212 const T*,
213 bool predicate)
214{
215 const char* const itname = type_name (it, (T*)0);
216 const char* const funname = predicate ? "LessThan" : "operator<()";
217
218 rw_info (0, 0, 0,
219 "std::equal_range (%s, %1$s, const UserClass&%{?}, %s%{;})",
220 itname, predicate, funname);
221
222#define TEST(str, val, loff, uoff, comp) \
223 test_equal_range (__LINE__, str, val, std::size_t (loff), \
224 std::size_t (uoff), std::size_t (comp), \
225 it, (T*)0, predicate)
226
227 // +------------------ source sequence
228 // | +------------ value argument
229 // | | +-------- lower offset of the returned pair
230 // | | | +----- upper offset of the returned pair
231 // | | | | +-- complexity: at most (2 * log(last - first) + 1)
232 // | | | | | comparisons (or applications of the predicate)
233 // | | | | |
234 // V V V V V
235 TEST ("", 'a', 0, 0, 0);
236 TEST ("a", 'a', 0, 1, 2);
237 TEST ("a", 'b', 1, 1, 1);
238 TEST ("b", 'a', 0, 0, 2);
239
240 TEST ("aa", 'a', 0, 2, 4);
241 TEST ("ab", 'a', 0, 1, 4);
242 TEST ("ab", 'b', 1, 2, 3);
243 TEST ("bb", 'a', 0, 0, 4);
244
245 TEST ("ace", 'a', 0, 1, 5);
246 TEST ("ace", 'b', 1, 1, 4);
247 TEST ("ace", 'c', 1, 2, 4);
248 TEST ("ace", 'd', 2, 2, 4);
249 TEST ("ace", 'e', 2, 3, 4);
250 TEST ("ace", 'f', 3, 3, 4);
251
252 TEST ("aceg", 'a', 0, 1, 6);
253 TEST ("aceg", 'b', 1, 1, 5);
254 TEST ("aceg", 'c', 1, 2, 5);
255 TEST ("aceg", 'd', 2, 2, 5);
256 TEST ("aceg", 'e', 2, 3, 5);
257 TEST ("aceg", 'f', 3, 3, 5);
258 TEST ("aceg", 'g', 3, 4, 5);
259 TEST ("aceg", 'h', 4, 4, 5);
260}
261
262
264static int rw_opt_no_fwd_iter;
265static int rw_opt_no_bidir_iter;
266static int rw_opt_no_rnd_iter;
267static int rw_opt_no_predicate;
268
269
270template <class T>
271void test_equal_range (const T*,
272 bool predicate)
273{
274 static const FwdIter<T> fwd_iter (0, 0, 0);
275 static const BidirIter<T> bidir_iter (0, 0, 0);
276 static const RandomAccessIter<T> rand_iter (0, 0, 0);
277
278 rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
279 "std::pair<%1$s, %1$s> std::equal_range "
280 "(%1$s, %1$s, const %2$s&%{?}, %s%{;})",
281 "ForwardIterator", "UserClass", predicate, "Compare",
282 predicate, "Compare");
283
284 if (rw_opt_no_fwd_iter) {
285 rw_note (0, 0, 0, "ForwardIterator test disabled");
286 }
287 else {
288 test_equal_range (fwd_iter, (T*)0, predicate);
289 }
290
292 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
293 }
294 else {
295 test_equal_range (bidir_iter, (T*)0, predicate);
296 }
297
298 if (rw_opt_no_fwd_iter) {
299 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
300 }
301 else {
302 test_equal_range (rand_iter, (T*)0, predicate);
303 }
304}
305
306
308static int
309run_test (int, char*[])
310{
311 test_equal_range ((UserClass*)0, false);
312
313 if (rw_opt_no_predicate) {
314 rw_note (0, __FILE__, __LINE__,
315 "test of the Predicate form of std::equal_range disabled");
316 }
317 else {
318 test_equal_range ((UserClass*)0, true);
319 }
320
321 return 0;
322}
323
324
326int main (int argc, char *argv[])
327{
328 return rw_test (argc, argv, __FILE__,
329 "lib.equal.range",
330 0 /* no comment */,
331 run_test,
332 "|-no-Predicate# "
333 "|-no-ForwardIterator# "
334 "|-no-BidirectionalIterator# "
335 "|-no-RandomAccessIterator#",
340}
#define T
Definition 17.names.cpp:163
#define rhs
Definition 17.names.cpp:536
#define line
Definition 17.names.cpp:490
#define comp
Definition 17.names.cpp:461
#define last
Definition 17.names.cpp:487
#define lhs
Definition 17.names.cpp:489
#define val
Definition 17.names.cpp:570
#define ForwardIterator
Definition 17.names.cpp:469
volatile int result
const MyBuffer< char > nsrc[]
int rw_opt_no_fwd_iter
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_predicate
#define TEST(str, val, loff, uoff, comp)
void test_equal_range(int line, const char *src_str, char val_char, std::size_t result_loff, std::size_t result_uoff, std::size_t ncomp, const ForwardIterator &it, const T *, bool predicate)
conv_to_bool operator<(const UserClass &lhs, const Y &rhs)
T value(const T &val)
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
#define RW_ASSERT(expr)
unsigned char UChar
Definition collate.cpp:122
static std::size_t funcalls_
bool operator()(const UserClass &lhs, const Y &rhs)
LessThan(int, int)
UserData data_
Definition rw_value.h:79
int val_
Definition rw_value.h:39
UserClass xval_
Y(const Y &rhs)
Y(char val, int)
static conv_to_bool make(bool val)