Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
20.auto.ptr.cpp
Go to the documentation of this file.
1
29#include <rw/_defs.h>
30
31#if defined (__IBMCPP__) && !defined (_RWSTD_NO_IMPLICIT_INCLUSION)
32 // disable implicit inclusion to work around
33 // a limitation in IBM VisualAge 5.0.2.0 (see PR #26959)
34# define _RWSTD_NO_IMPLICIT_INCLUSION
35#endif
36
37#include <memory>
38
39
41#ifndef _RWSTD_EXPLICIT_INSTANTIATION
42
43 // explicitly instantiate
44
45# if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD)
46
47 // verify that names are declared [only[ in namespace std
48
49# define TEST_CLASS_DEF(name, Tparam) \
50 template class std::name Tparam \
51 /* void name (void *name) */
52
53# else // if defined (_RWSTD_NO_NAMESPACE) || defined (_RWSTD_NO_HONOR_STD)
54
55 // verify that names do not collide with function argument names
56
57# define TEST_CLASS_DEF(name, Tparam) \
58 template class std::name Tparam; \
59 void foo (void *name)
60
61# endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD
62
63#else // if defined (_RWSTD_EXPLICIT_INSTANTIATION)
64
65 // classes will implicitly instantiated below
66
67# if !defined (_RWSTD_NO_NAMESPACE) && !defined (_RWSTD_NO_HONOR_STD)
68
69 // verify that names are declared [only] in namespace std
70
71# define TEST_CLASS_DEF(name, ignore) void name (void *name)
72
73# else // if defined (_RWSTD_NO_NAMESPACE) || defined (_RWSTD_NO_HONOR_STD)
74
75# define TEST_CLASS_DEF(name, ignore) void foo (void *name)
76
77# endif // !_RWSTD_NO_NAMESPACE && !_RWSTD_NO_HONOR_STD
78
79#endif // _RWSTD_EXPLICIT_INSTANTIATION
80
81
82// auto_ptr_ref instantiated first to prevent bogus MSVC 6.0 warning C4660:
83// template-class specialization 'auto_ptr_ref<int>' is already instantiated
84// follows lwg issue 127
85TEST_CLASS_DEF (auto_ptr_ref, <int>);
86
87TEST_CLASS_DEF (auto_ptr, <int>);
88
89
91#include <rw_cmdopt.h> // for rw_enabled()
92#include <rw_driver.h> // for rw_assert(), rw_test(), ...
93
94
96struct Base
97{
98 int i_; // unique object id
99
100 static int cnt_; // object counter
101 static int gen_; // unique id generator
102
103 Base (): i_ (gen_++) { ++cnt_; }
104
105 ~Base () {
106 --cnt_;
107 }
108
109 static void sink (std::auto_ptr<Base>) { }
110};
111
112int Base::cnt_; // Base object counter
113int Base::gen_; // Base unique id generator
114
115struct Derived: Base
116{
117 static std::auto_ptr<Derived> source () {
118 return std::auto_ptr<Derived> ();
119 }
120
121 static void sink (std::auto_ptr<Derived>) { }
122};
123
124
125// helpers to verify that each class' ctor is explicit
126// not defined since they must not be referenced if test is successful
127void is_explicit (const std::auto_ptr<Base>&);
128
130{
131 // NOT explicit
132#ifndef _RWSTD_NO_NATIVE_BOOL
133
135
136#endif // _RWSTD_NO_NATIVE_BOOL
137
140 has_implicit_ctor (double*) { }
141 has_implicit_ctor (void**) { }
143};
144
146
147
148template <class T>
149void test_auto_ptr (T*, const char *tname)
150{
151 rw_info (0, 0, 0, "std::auto_ptr<%s>", tname);
152
153 if (!rw_enabled (tname)) {
154 rw_note (0, 0, __LINE__, "auto_ptr<%s> test disabled", tname);
155 return;
156 }
157
158 // exercise 20.4.5, p2 - auto_ptr<> interface
159
160 typedef typename std::auto_ptr<T>::element_type element_type;
161
162 // verify that element_type is the same as T
163 element_type *elem = (T*)0;
164
165 // verify that default ctor is explicit
166 is_explicit (elem);
167
168
169// verify that a member function is accessible and has the appropriate
170// signature, including return type and exception specification
171#define FUN(result, T, name, arg_list) do { \
172 result (std::auto_ptr<T>::*pf) arg_list = &std::auto_ptr<T>::name; \
173 _RWSTD_UNUSED (pf); \
174 } while (0)
175
176#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
177
178 // working around a bug in aCC (see PR #24430)
179 FUN (std::auto_ptr<T>&, T, operator=, (std::auto_ptr<T>&) _PTR_THROWS(()));
180
181#endif // HP aCC > 5
182
183 FUN (T&, T, operator*, () const _PTR_THROWS (()));
184
185#ifndef _RWSTD_NO_NONCLASS_ARROW_RETURN
186
187 FUN (T*, T, operator->, () const _PTR_THROWS (()));
188
189#endif // _RWSTD_NO_NONCLASS_ARROW_RETURN
190
191 FUN (T*, T, get, () const _PTR_THROWS (()));
192 FUN (T*, T, release, () _PTR_THROWS (()));
193 FUN (void, T, reset, (T*) _PTR_THROWS (()));
194
195
196#if !defined(__GNUG__) || __GNUG__ > 3 || __GNUG__ == 3 && __GNUC_MINOR__ > 2
197
198 // g++ 2.95.2 and HP aCC can't take the address of a template member
199
200# if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
201
202 // SunPro incorrectly warns here (see PR #27276)
203 FUN (std::auto_ptr<Base>&, Base,
204 operator=, (std::auto_ptr<Derived>&) _PTR_THROWS (()));
205
206 // SunPro 5.4 can't decide between a ctor template
207 // and a conversion operator (see PR #24476)
208# if !defined (__SUNPRO_CC) || __SUNPRO_CC > 0x540
209
210# if !defined (_RWSTD_MSVC) || _RWSTD_MSVC > 1310
211 FUN (std::auto_ptr_ref<Base>, Derived,
212 operator std::auto_ptr_ref<Base>, () _PTR_THROWS (()));
213
214 FUN (std::auto_ptr<Base>, Derived,
215 operator std::auto_ptr<Base>, () _PTR_THROWS (()));
216
217# endif // MSVC > 7.1
218
219# endif // SunPro > 5.4
220
221# endif // HP aCC > 5
222
223#endif // gcc > 3.2
224
225 rw_info (0, 0, 0, "[lib.auto.ptr.cons]");
226
227 T *pt = new T ();
228
229 // 20.4.5.1, p1
230 std::auto_ptr<T> ap1 (pt);
231 rw_assert (pt == ap1.get (), 0, __LINE__,
232 "auto_ptr<%s>::auto_ptr (%1$s*)", tname);
233
234 // 20.4.5.1, p2
235 std::auto_ptr<T> ap2 (ap1);
236 rw_assert (0 == ap1.get (), 0, __LINE__,
237 "auto_ptr<%s>::auto_ptr (auto_ptr&", tname);
238 rw_assert (pt == ap2.get (), 0, __LINE__,
239 "auto_ptr<%s>::auto_ptr (auto_ptr&)", tname);
240
241 // 20.4.5.1, p7, 8, 9
242 ap1 = ap2;
243 rw_assert (0 == ap2.get (), 0, __LINE__,
244 "auto_ptr<%s>::operator= (auto_ptr&)", tname);
245 rw_assert (pt == ap1.get (), 0, __LINE__,
246 "auto_ptr<%s>::operator= (auto_ptr&)", tname);
247
248
249 rw_info (0, 0, 0, "[lib.auto.ptr.members]");
250
251 // 20.4.5.2, p2
252 rw_assert (*ap1.get () == ap1.operator*(), 0, __LINE__,
253 "auto_ptr<%s>::operator*()", tname);
254
255 // 20.4.5.2, p3
256 rw_assert (ap1.get () == ap1.operator->(), 0, __LINE__,
257 "auto_ptr<%s>::operator->()", tname);
258
259 // 20.4.5.2, p4
260 rw_assert (pt == ap1.get (), 0, __LINE__,
261 "auto_ptr<%s>::get ()", tname);
262
263 // 20.4.5.2, p5, 6
264 rw_assert (pt == ap1.release () && 0 == ap1.get (), 0, __LINE__,
265 "auto_ptr<%s>::release ()", tname);
266
267
268 // 20.4.5.2, p7
269 ap1.reset (pt);
270 rw_assert (pt == ap1.get (), 0, __LINE__,
271 "auto_ptr<%s>::reset ()", tname);
272}
273
274
276static void
277test_auto_ptr_void ()
278{
279 // note that specializing auto_ptr on void is undefined
280 // due to 17.4.3.6, p2; this is an extension of this
281 // implementation
282 rw_info (0, 0, 0, "std::auto_ptr<void> [extension]");
283
284 std::auto_ptr<void> ap1;
285 std::auto_ptr<void> ap2 ((void*)0);
286 std::auto_ptr<void> ap3 (ap2);
287
288 ap1 = ap1;
289 ap1.operator= (ap1);
290
291#if !defined (__HP_aCC) || 6 <= _RWSTD_HP_aCC_MAJOR
292
293 // working around an HP aCC 3 and 5 bug (STDCXX-655)
294
295 ap1.operator=<void>(ap1);
296
297#endif // !HP aCC or HP aCC 6 and better
298
299 std::auto_ptr<int> ap4;
300 ap1 = ap4;
301 ap1.operator= (ap4);
302 ap1.operator=<int>(ap4);
303
304 // operator*() cannot be instantiated
305
306 void* pv;
307
308 pv = ap1.operator->();
309 pv = ap1.get ();
310 pv = ap1.release ();
311
312 ap1.reset ();
313 ap1.reset (pv);
314
315#if !defined (__HP_aCC) || 6 <= _RWSTD_HP_aCC_MAJOR
316
317 // working around an HP aCC 3 and 5 bug (STDCXX-656)
318
319 const std::auto_ptr_ref<void> ar = ap1.operator std::auto_ptr_ref<void>();
320 const std::auto_ptr<void> ap5 = ap1.operator std::auto_ptr<void>();
321
322 _RWSTD_UNUSED (ar);
323 _RWSTD_UNUSED (ap5);
324
325#endif // !HP aCC or HP aCC 6 and better
326}
327
328
330// exercise 20.4.5.4
331static std::auto_ptr<Derived>
332test_auto_ptr_conversions ()
333{
334 rw_info (0, 0, 0, "[lib.auto.ptr.conv]");
335
336 // 20.4.5.1, p4, 5, 6
337 Derived *pd = new Derived;
338 std::auto_ptr<Derived> ap1 (pd);
339 rw_assert (pd == ap1.get (), 0, __LINE__,
340 "auto_ptr::auto_ptr ()");
341
342 std::auto_ptr<Base> ap2 (ap1);
343
344 rw_assert (0 == ap1.get (), 0, __LINE__,
345 "auto_ptr<Base>::auto_ptr(auto_ptr<Derived>&)");
346 rw_assert (_RWSTD_STATIC_CAST (Base*, pd) == ap2.get (), 0, __LINE__,
347 "auto_ptr<Base>::auto_ptr(auto_ptr<Derived>&)");
348
349 ap2.reset (pd);
350
351 // 20.4.5.2, p7 - must not delete owning pointer
352 ap2.reset (pd);
353 rw_assert (pd == ap2.get (), 0, __LINE__, "auto_ptr::reset ()");
354
355 pd = new Derived;
356 ap2.reset (pd); // must delete owning pointer
357 rw_assert (pd == ap2.get (), 0, __LINE__, "auto_ptr::reset ()");
358
359 // 20.4.5.3, p1, 2, 3 - creates an auto_ptr_ref
360 pd = new Derived;
361 std::auto_ptr<Base> ap3 =
362 std::auto_ptr<Base>(std::auto_ptr<Derived>(pd));
363
364 rw_assert ((Base*)pd == ap3.get (), 0, __LINE__,
365 "auto_ptr<>::auto_ptr(std::auto_ptr_ref)");
366
367#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
368
369 pd = new Derived;
370 std::auto_ptr<Derived> ap4 (pd);
371 ap3 = std::auto_ptr<Base> (ap4);
372
373 rw_assert (0 == ap4.get () && (Base*)pd == ap3.get (), 0, __LINE__,
374 "auto_ptr<>::operator auto_ptr<>()");
375
376#endif // HP aCC > 5
377
378 {
379 // see CWG issue 84 for some background on the sequence below
380 // http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_defects.html#84
381
382 std::auto_ptr<Derived> pd1 (Derived::source ());
383 std::auto_ptr<Derived> pd2 (pd1);
384
385#if !defined (__HP_aCC) || _RWSTD_HP_aCC_MAJOR > 5
386
388
389#endif // HP aCC > 5
390
391 pd1 = pd2;
392 pd1 = Derived::source();
393 std::auto_ptr<Base> pb1 (Derived::source ());
394 std::auto_ptr<Base> pb2 (pd1);
395
396 // conversion sequence:
397 // 1. auto_ptr<Derived>::operator auto_ptr<Base>() [UDC]
398 // 2. auto_ptr<Base>::operator auto_ptr_ref<Base>() [UDC]
399 // 3. auto_ptr<Base>(auto_ptr_ref<Base>) [UDC]
400
401 // since the conversion sequence involves more than one UDC
402 // (User-Defined Conversion), it is illegal
403 // Base::sink (Derived::source ());
404
405 pb1 = pd2;
406 pb1 = Derived::source ();
407
408 return pd1;
409 }
410}
411
412
413
415static int rw_opt_no_conversions; // for --no-conversions
416
417
418static int
419run_test (int, char**)
420{
421
422#ifndef _RWSTD_NO_NATIVE_BOOL
423
424 test_auto_ptr ((bool*)0, "bool");
425
426#endif // _RWSTD_NO_NATIVE_BOOL
427
428 test_auto_ptr ((char*)0, "char");
429 test_auto_ptr ((int*)0, "int");
430 test_auto_ptr ((double*)0, "double");
431 test_auto_ptr ((void**)0, "void*");
432
433 int count = Base::cnt_;
434
435 // exercise 20.4.5.4
436 if (rw_opt_no_conversions)
437 rw_note (0, 0, 0, "conversions test disabled");
438 else
439 test_auto_ptr_conversions ();
440
441 // verify that no objects leaked
442 rw_assert (count == Base::cnt_, 0, __LINE__,
443 "autoptr leaked %d objects", Base::cnt_ - count);
444
445 if (!rw_enabled ("void"))
446 rw_note (0, 0, 0, "auto_ptr<void> test disabled");
447 else
448 test_auto_ptr_void ();
449
450 return 0;
451}
452
453
455int main (int argc, char *argv[])
456{
457 return rw_test (argc, argv, __FILE__,
458 "lib.auto.ptr",
459 0 /* no comment */,
460 run_test,
461 "|-no-conversions#",
462 &rw_opt_no_conversions,
463 (void*)0 /* sentinel */);
464}
void count(T, T, const U &,...)
#define T
Definition 17.names.cpp:163
#define _PTR_THROWS(spec)
void test_auto_ptr(T *, const char *tname)
#define TEST_CLASS_DEF(name, Tparam)
#define FUN(result, T, name, arg_list)
void is_explicit(const std::auto_ptr< Base > &)
void run_test(const ForwardIterator &dummy, T *, Predicate *pred)
#define main
volatile double * pd
#define _RWSTD_UNUSED(arg)
Definition _defs.h:972
#define _RWSTD_STATIC_CAST(T, x)
Definition _defs.h:534
_TEST_EXPORT int rw_enabled(const char *name)
_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
static int gen_
static int cnt_
static void sink(std::auto_ptr< Base >)
static void sink(std::auto_ptr< Derived >)
static std::auto_ptr< Derived > source()
has_implicit_ctor(void **)
has_implicit_ctor(double *)