Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
25.lower.bound.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>
38#include <cstring>
39
40#include <rw_alg_test.h>
41#include <rw_value.h> // for UserClass
42#include <rw_driver.h>
43
44
46// distinct and not Less-Than-Comparable with class UserClass (except as
47// defined below) to detect unwarranted assumptions made by the
48// implementation of the algorithms
49struct Y
50{
52
53 // not Default-Constructible
54 Y (int /* dummy */, int /*dummy */): xval_ () { }
55
56 // CopyConstructible
57 Y (const Y &rhs): xval_ (rhs.xval_) { }
58
59private:
60
61 void operator=(Y&); // not Assignable
62};
63
65operator< (const UserClass &lhs, const Y &rhs)
66{
67 return conv_to_bool::make (lhs < rhs.xval_);
68}
69
70
72// predicate used as the Compare argument to lower_bound()
73struct LessThan
74{
75 static std::size_t funcalls_;
76
77 LessThan (int /* dummy */, int /* dummy */) {
78 funcalls_ = 0;
79 }
80
81 // return a type other than bool but one that is implicitly
82 // convertible to bool to detect incorrect assumptions
84 ++funcalls_;
85 return conv_to_bool::make (lhs < rhs.xval_);
86 }
87
88private:
89 void operator= (LessThan&); // not assignable
90};
91
92std::size_t LessThan::funcalls_;
93
94
96template <class ForwardIterator>
98 const char *src_str,
99 char val_char,
100 std::size_t result_off,
101 std::size_t ncomp,
102 const ForwardIterator*,
103 const char *itname,
104 bool predicate)
105{
106 RW_ASSERT (0 != src_str);
107
108 const std::size_t nsrc = std::strlen (src_str);
109 UserClass* const xsrc = UserClass::from_char (src_str, nsrc);
110
111 if (nsrc < result_off)
112 result_off = nsrc;
113
114 // construct the source range to pass to the algorithm
115 const ForwardIterator first (xsrc, xsrc, xsrc + nsrc);
116 const ForwardIterator last (xsrc + nsrc, xsrc + nsrc, xsrc + nsrc);
117
118 // construct the object to pass to the algorithm
119 // the type of the object is distinct from the iterator's value_type
120 // to detect unwarranted assumptions made by the implementation
121 Y value (0, 0 /* dummy arguments */);
122 value.xval_.data_.val_ = val_char;
123
124 // construct the Compare function object to pass to the algorithm
125 // when `predicate' is true
126 const LessThan comp (0, 0 /* dummy arguments */);
127
128 // reset the counter of invocations of UserClass::operator<()
130
131 // invoke the appropriate form of the algorithm, storing
132 // the resturned value
134 ? std::lower_bound (first, last, value, comp)
135 : std::lower_bound (first, last, value);
136
137 // silence bogus EDG eccp 3.6 remark #550-D:
138 // variable was set but never used
140
141 // verify correctness
142 const std::size_t off = std::size_t (result.cur_ - xsrc);
143
144 rw_assert (off == result_off, 0, line,
145 "lower_bound(%s = \"%s\", ...%{?}%#c%{;}) ==> "
146 "first + %zu, got %zu",
147 itname, src_str, !predicate, val_char,
148 off, result_off);
149
150 // verify complexity
151 const std::size_t funcalls = predicate
153
154 rw_assert (funcalls <= ncomp, 0, line,
155 "lower_bound(%s = \"%s\", ...%{?}%#c%{;}) complexity: "
156 "invoked predicate at most %zu times, got %zu",
157 itname, src_str, !predicate, val_char,
158 ncomp, funcalls);
159
160 delete[] xsrc;
161}
162
163
165template <class ForwardIterator>
167 const char *itname,
168 bool predicate)
169{
170#define TEST(str, val, off, comp) \
171 test_lower_bound (__LINE__, str, val, std::size_t (off), \
172 std::size_t (comp), (ForwardIterator*)0, \
173 itname, predicate)
174
175 rw_info (0, 0, 0,
176 "std::lower_bound (%s, %1$s, const UserClass&%{?}, %s%{;})",
177 itname, predicate, "LessThan");
178
179 // +--------------- source sequence
180 // | +--------- value argument
181 // | | +----- offset of the resturned iterator, -1 for end
182 // | | | +-- complexity: at most (log(last - first) + 1)
183 // | | | | comparisons (or applications of the predicate)
184 // | | | |
185 // V V V V
186 TEST ("", 'a', 0, 0);
187 TEST ("a", 'a', 0, 1);
188 TEST ("a", 'b', 1, 1);
189 TEST ("b", 'a', 0, 1);
190
191 TEST ("aa", 'a', 0, 2);
192 TEST ("ab", 'a', 0, 2);
193 TEST ("ab", 'b', 1, 2);
194 TEST ("bb", 'a', 0, 2);
195
196 TEST ("ace", 'a', 0, 3);
197 TEST ("ace", 'b', 1, 3);
198 TEST ("ace", 'c', 1, 3);
199 TEST ("ace", 'd', 2, 3);
200 TEST ("ace", 'e', 2, 3);
201 TEST ("ace", 'f', 3, 3);
202
203 TEST ("aceg", 'a', 0, 3);
204 TEST ("aceg", 'b', 1, 3);
205 TEST ("aceg", 'c', 1, 3);
206 TEST ("aceg", 'd', 2, 3);
207 TEST ("aceg", 'e', 2, 3);
208 TEST ("aceg", 'f', 3, 3);
209 TEST ("aceg", 'g', 3, 3);
210 TEST ("aceg", 'h', 4, 3);
211}
212
213
215static int rw_opt_no_fwd_iter;
216static int rw_opt_no_bidir_iter;
217static int rw_opt_no_rnd_iter;
218static int rw_opt_no_predicate;
219
220
221static void
223{
224 rw_info (0, 0, 0, "template <class %s, class %s%{?}, class %s%{;}> "
225 "std::lower_bound (%1$s, %1$s, const UserClass&%{?}, %4$s%{;})",
226 "ForwardIterator", "UserClass", predicate, "Compare", predicate);
227
228 if (rw_opt_no_fwd_iter) {
229 rw_note (0, 0, 0, "ForwardIterator test disabled");
230 }
231 else {
232 test_lower_bound ((FwdIter<UserClass>*)0, "ForwardIterator", predicate);
233 }
234
235 if (rw_opt_no_bidir_iter) {
236 rw_note (0, 0, 0, "BidirectionalIterator test disabled");
237 }
238 else {
239 test_lower_bound ((BidirIter<UserClass>*)0, "BidirectionalIterator",
240 predicate);
241 }
242
243 if (rw_opt_no_fwd_iter) {
244 rw_note (0, 0, 0, "RandomAccessIterator test disabled");
245 }
246 else {
248 "RandomAccessIterator", predicate);
249 }
250}
251
252
254static int
255run_test (int, char*[])
256{
257 test_lower_bound (false);
258
259 if (rw_opt_no_predicate) {
260 rw_note (0, __FILE__, __LINE__,
261 "test of the Predicate form of std::lower_bound disabled");
262 }
263 else {
264 test_lower_bound (true);
265 }
266
267 return 0;
268}
269
270
272int main (int argc, char *argv[])
273{
274 return rw_test (argc, argv, __FILE__,
275 "lib.lower.bound",
276 0 /* no comment */,
277 run_test,
278 "|-no-Predicate# "
279 "|-no-ForwardIterator# "
280 "|-no-BidirectionalIterator# "
281 "|-no-RandomAccessIterator#",
286}
#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 off
Definition 17.names.cpp:507
#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
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define TEST(str, val, off, comp)
void test_lower_bound(int line, const char *src_str, char val_char, std::size_t result_off, std::size_t ncomp, const ForwardIterator *, const char *itname, bool predicate)
conv_to_bool operator<(const UserClass &lhs, const Y &rhs)
T value(const T &val)
#define main
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
_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)
static std::size_t funcalls_
bool operator()(const UserClass &lhs, const Y &rhs)
LessThan(int, int)
static UserClass from_char(char c)
Definition rw_value.h:221
static _RWSTD_SIZE_T n_total_op_lt_
Definition rw_value.h:133
Y(int, int)
UserClass xval_
Y(const Y &rhs)
static conv_to_bool make(bool val)