Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
26.accumulate.cpp
Go to the documentation of this file.
1
29#include <numeric> // for accumulate
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
38// plus-assign
39template <class T>
40struct plus_asgn: T
41{
43 unused = rhs.unused;
44 return *this;
45 }
46private:
47 // unused member prevents bogus HP aCC warnings (see Onyx #23561)
48 int unused;
49};
50
52
53// disable explicit instantiation for compilers (like MSVC)
54// that can't handle it
55#ifndef _RWSTD_NO_EXPLICIT_INSTANTIATION
56
57template
62
63template
65accumulate (InputIter<assign<base<cpy_ctor> > >,
69
70#endif // _RWSTD_NO_EXPLICIT_INSTANTIATION
71
72} // namespace std
73
74
76struct Y: public UserClass
77{
78 // number of times the object's += operator has been invoked,
79 // regardless of whether the operation threw an exception or not
80 std::size_t n_op_plus_assign_;
81
82 static std::size_t n_total_op_plus_assign_; // ... += operators ...
83
84 // class thrown from the respective functions
86
87 // throw object's `id' wrapped in the appropriate struct when the
88 // corresponding n_total_xxx_ counter reaches the value pointed to
89 // by the respective pointer below
90 static std::size_t* op_plus_assign_throw_ptr_;
91
92 // objects to which the pointers above initally point
93 static std::size_t op_plus_assign_throw_count_;
94
95 Y (): UserClass () { /* empty */ }
96
97 Y (const Y &rhs): UserClass (rhs) { /* empty */ }
98
99 Y& operator+= (const Y& rhs) {
100
101 // verify id validity and uniqueness
102 RW_ASSERT (id_ && id_ <= id_gen_);
103 RW_ASSERT (rhs.id_ && rhs.id_ <= id_gen_);
104 RW_ASSERT (this == &rhs || id_ != rhs.id_);
105
106 // increment the number of times each distinct object
107 // has been used as the argument to operator+=
108 // (do so even if the function throws an exception below)
109 ++n_op_plus_assign_;
110
111 if (this != &rhs)
112 ++_RWSTD_CONST_CAST (Y*, &rhs)->n_op_plus_assign_;
113
114 // increment the total number of invocations of the operator
115 // (do so even if the function throws an exception below)
116 ++n_total_op_plus_assign_;
117
118#ifndef _RWSTD_NO_EXCEPTIONS
119
120 // throw an exception if the number of calls
121 // to operator== reaches the given value
122
123 if ( op_plus_assign_throw_ptr_
124 && n_total_op_plus_assign_ == *op_plus_assign_throw_ptr_) {
125 OpPlusAssign ex;
126 ex.id_ = id_;
127 throw ex;
128 }
129
130#endif // _RWSTD_NO_EXCEPTIONS
131
132 data_.val_ += rhs.data_.val_;
133 return *this;
134 }
135};
136
137/* static */ std::size_t Y::n_total_op_plus_assign_;
138/* static */ std::size_t* Y::op_plus_assign_throw_ptr_ =
140/* static */ std::size_t Y::op_plus_assign_throw_count_ =
141 std::size_t (-1);
142
143
145template <class T>
147{
148 static conv_to_T make (T val) {
149 return conv_to_T (val);
150 }
151
152 // strictly convertible to a T value
153 operator T () const {
154 return val_;
155 }
156
157private:
158 // not (publicly) Default-Constructible
159 conv_to_T (T val): val_ (val) { }
160
161 void operator= (conv_to_T); // not Assignable
162 void operator!() const; // not defined
163
164 T val_;
165};
166
167
170{
171 static std::size_t funcalls_;
172
173 // dummy arguments provided to prevent the class from being
174 // default constructible and implicit conversion from int
175 Accumulator (int /* dummy */, int /* dummy */) {
176 funcalls_ = 0;
177 }
178
179 // return a type convertible to Y
180 conv_to_T<Y> operator() (const Y &x, const Y &y) /* non-const */ {
181 ++funcalls_;
182 Y res (x);
183 res.data_.val_ += y.data_.val_;
184 return conv_to_T<Y>::make (res);
185 }
186
187private:
188 void operator= (Accumulator&); // not assignable
189};
190
191std::size_t Accumulator::funcalls_;
192
193
195// exercises accumulate (26.4.1)
196template <class T, class InputIterator, class BinaryOp>
197void test_accumulate (const std::size_t N,
198 const InputIterator &it,
199 const T*,
200 const BinaryOp *op)
201{
202 const char* const itname = type_name (it, (T*)0);
203 const char* const tname = "Y";
204 const char* const opname = "BinaryOperation";
205
206 rw_info (0, 0, 0, "std::accumulate (%s, %1$s, %s%{?}, %s%{;})",
207 itname, tname, 0 != op, opname);
208
209 // construct initial T
210 const T init;
211 int sum = init.data_.val_;
212
213 T::gen_ = gen_seq;
214
215 T* const buf = new T [N];
216
217 for (std::size_t i = 0; i != N; ++i) {
218
219 T* const buf_end = buf + i;
220
221 const InputIterator first (buf, buf, buf_end);
222 const InputIterator last (buf_end, buf, buf_end);
223
224 BinaryOp bin_op (0, 0);
225
226 const T res = op ?
227 std::accumulate (first, last, init, bin_op)
228 : std::accumulate (first, last, init);
229
230 // verify the result 26.4.1, p1
231 bool success = sum == res.data_.val_;
232 rw_assert (success, 0, __LINE__,
233 "step %zu: accumulate <%s, %s%{?}, %s%{;}> "
234 "= %d, expected %d",
235 i + 1, itname, tname, 0 != op, opname, res.data_.val_, sum);
236
237 sum += buf [i].data_.val_;
238
239 if (!success)
240 break;
241 }
242
243 delete[] buf;
244}
245
246
248/* extern */ int rw_opt_nloops = 256; // --nloops
249/* extern */ int rw_opt_no_binary_op; // --no-binary_op
250/* extern */ int rw_opt_no_input_iter; // --no-InputIterator
251/* extern */ int rw_opt_no_fwd_iter; // --no-ForwardIterator
252/* extern */ int rw_opt_no_bidir_iter; // --no-BidirectionalIterator
253/* extern */ int rw_opt_no_rnd_iter; // --no-RandomAccessIterator
254
255
257template <class T, class BinaryOp>
258void test_accumulate (const std::size_t N,
259 const T*,
260 const BinaryOp *op)
261{
262 static const InputIter<T> input_iter (0, 0, 0);
263 static const ConstFwdIter<T> fwd_iter (0, 0, 0);
264 static const ConstBidirIter<T> bidir_iter (0, 0, 0);
265 static const ConstRandomAccessIter<T> rand_iter (0, 0, 0);
266
267 rw_info (0, 0, 0,
268 "template <class %s, class %s%{?}, class %s%{;}> "
269 "%2$s std::accumulate (%1$s, %1$s, %2$s%{?}, %s%{;})",
270 "InputIterator", "T", 0 != op, "BinaryOperation",
271 0 != op, "BinaryOperation");
272
274 rw_note (0, 0, __LINE__, "InputIterator test disabled");
275 }
276 else {
277 test_accumulate (N, input_iter, (T*)0, op);
278 }
279
280 if (rw_opt_no_fwd_iter) {
281 rw_note (0, 0, __LINE__, "ForwardIterator test disabled");
282 }
283 else {
284 test_accumulate (N, fwd_iter, (T*)0, op);
285 }
286
288 rw_note (0, 0, __LINE__, "BidirectionalIterator test disabled");
289 }
290 else {
291 test_accumulate (N, bidir_iter, (T*)0, op);
292 }
293
294 if (rw_opt_no_rnd_iter) {
295 rw_note (0, 0, __LINE__, "RandomAccessIterator test disabled");
296 }
297 else {
298 test_accumulate (N, rand_iter, (T*)0, op);
299 }
300
301}
302
303
305static int
306run_test (int, char*[])
307{
308 const std::size_t N = std::size_t (rw_opt_nloops);
309
310 test_accumulate (N, (Y*)0, (Accumulator*)0);
311
313 rw_note (0, 0, 0, "accumulate with binary operation test disabled");
314 else
315 test_accumulate (N, (Y*)0, (Accumulator*)1);
316
317 return 0;
318}
319
320
322int main (int argc, char *argv[])
323{
324 return rw_test (argc, argv, __FILE__,
325 "lib.accumulate",
326 0 /* no comment */, run_test,
327 "|-nloops#0 " // must be non-negative
328 "|-no-binary_op#"
329 "|-no-InputIterator# "
330 "|-no-ForwardIterator# "
331 "|-no-BidirectionalIterator# "
332 "|-no-RandomAccessIterator#",
339}
#define N
Definition 17.names.cpp:157
#define i
Definition 17.names.cpp:126
#define T
Definition 17.names.cpp:163
#define y
Definition 17.names.cpp:141
#define rhs
Definition 17.names.cpp:536
#define res
Definition 17.names.cpp:531
#define last
Definition 17.names.cpp:487
#define x
Definition 17.names.cpp:140
#define buf
Definition 17.names.cpp:452
#define val
Definition 17.names.cpp:570
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
int rw_opt_no_fwd_iter
int rw_opt_no_binary_op
void test_accumulate(const std::size_t N, const InputIterator &it, const T *, const BinaryOp *op)
int rw_opt_no_rnd_iter
int rw_opt_no_bidir_iter
int rw_opt_no_input_iter
int rw_opt_nloops
const char * type_name()
#define main
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
std::mbstate_t init
Definition codecvt1.cpp:80
Definition json.h:5363
_TEST_EXPORT int gen_seq()
Definition alg_test.cpp:38
_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)
Accumulator(int, int)
conv_to_T< Y > operator()(const Y &x, const Y &y)
static std::size_t funcalls_
const int id_
Definition rw_value.h:81
UserData data_
Definition rw_value.h:79
static int id_gen_
Definition rw_value.h:121
int val_
Definition rw_value.h:39
static std::size_t * op_plus_assign_throw_ptr_
static std::size_t op_plus_assign_throw_count_
static std::size_t n_total_op_plus_assign_
std::size_t n_op_plus_assign_
Y(const Y &rhs)
static conv_to_T make(T val)
plus_asgn & operator+=(const plus_asgn &rhs)