]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/contract/old.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / contract / old.hpp
CommitLineData
11fdf7f2
TL
1
2#ifndef BOOST_CONTRACT_OLD_HPP_
3#define BOOST_CONTRACT_OLD_HPP_
4
5// Copyright (C) 2008-2018 Lorenzo Caminiti
6// Distributed under the Boost Software License, Version 1.0 (see accompanying
7// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
8// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
9
10/** @file
11Handle old values.
12*/
13
14#include <boost/contract/core/config.hpp>
15#include <boost/contract/core/virtual.hpp>
16#ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
17 #include <boost/contract/detail/checking.hpp>
18#endif
19#include <boost/contract/detail/operator_safe_bool.hpp>
20#include <boost/contract/detail/declspec.hpp>
21#include <boost/contract/detail/debug.hpp>
22#include <boost/make_shared.hpp>
23#include <boost/shared_ptr.hpp>
24#include <boost/type_traits/is_copy_constructible.hpp>
25#include <boost/utility/enable_if.hpp>
26#include <boost/static_assert.hpp>
27#include <boost/preprocessor/control/expr_iif.hpp>
28#include <boost/preprocessor/config/config.hpp>
29#include <queue>
30
31#if !BOOST_PP_VARIADICS
32
33#define BOOST_CONTRACT_OLDOF \
34BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_program_old_values
35
36#else // variadics
37
38#include <boost/preprocessor/facilities/overload.hpp>
39#include <boost/preprocessor/facilities/empty.hpp>
40#include <boost/preprocessor/cat.hpp>
41#include <boost/config.hpp>
42
43/* PRIVATE */
44
45/** @cond */
46
47#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
48 #define BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value) /* nothing */
49#else
50 #include <boost/typeof/typeof.hpp>
51 // Explicitly force old_ptr<...> conversion to allow for C++11 auto decl.
52 #define BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value) \
53 boost::contract::old_ptr<BOOST_TYPEOF(value)>
54#endif
55
56#define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_2( \
57 v, value) \
58 BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value)(boost::contract::make_old(v, \
59 boost::contract::copy_old(v) ? (value) : boost::contract::null_old() \
60 ))
61
62#define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_1( \
63 value) \
64 BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value)(boost::contract::make_old( \
65 boost::contract::copy_old() ? (value) : boost::contract::null_old() \
66 ))
67
68/** @endcond */
69
70/* PUBLIC */
71
72// NOTE: Leave this #defined the same regardless of ..._NO_OLDS.
73/**
74Macro typically used to copy an old value expression and assign it to an old
75value pointer.
76
77The expression expanded by this macro should be assigned to an old value
78pointer of type @RefClass{boost::contract::old_ptr} or
79@RefClass{boost::contract::old_ptr_if_copyable}.
80This is an overloaded variadic macro and it can be used in the following
81different ways.
82
831\. From within virtual public functions and public functions overrides:
84
85@code
86BOOST_CONTRACT_OLDOF(v, old_expr)
87@endcode
88
892\. From all other operations:
90
91@code
92BOOST_CONTRACT_OLDOF(old_expr)
93@endcode
94
95Where:
96
97@arg <c><b>v</b></c> is the extra parameter of type
98 @RefClass{boost::contract::virtual_}<c>*</c> and default value @c 0
99 from the enclosing virtual public function or public function
100 overrides declaring the contract.
92f5a8d4 101@arg <c><b>old_expr</b></c> is the expression to be evaluated and copied into
11fdf7f2
TL
102 the old value pointer.
103 (This is not a variadic macro parameter so any comma it might contain
92f5a8d4 104 must be protected by round parenthesis and
11fdf7f2
TL
105 <c>BOOST_CONTRACT_OLDOF(v, (old_expr))</c> will always work.)
106
107On compilers that do not support variadic macros, programmers can manually copy
108old value expressions without using this macro (see
109@RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}).
110
111@see @RefSect{tutorial.old_values, Old Values}
112*/
113#define BOOST_CONTRACT_OLDOF(...) \
114 BOOST_PP_CAT( /* CAT(..., EMTPY()) required on MSVC */ \
115 BOOST_PP_OVERLOAD( \
116 BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_, \
117 __VA_ARGS__ \
118 )(__VA_ARGS__), \
119 BOOST_PP_EMPTY() \
120 )
121
122#endif // variadics
123
124/* CODE */
125
126namespace boost { namespace contract {
127
128/**
129Trait to check if an old value type can be copied or not.
130
131By default, this unary boolean meta-function is equivalent to
132@c boost::is_copy_constructible<T> but programmers can chose to specialize it
92f5a8d4 133for user-defined types (in general some kind of specialization is also needed on
11fdf7f2
TL
134compilers that do not support C++11, see
135<a href="http://www.boost.org/doc/libs/release/libs/type_traits/doc/html/boost_typetraits/reference/is_copy_constructible.html">
136<c>boost::is_copy_constructible</c></a>):
137
138@code
92f5a8d4 139class u; // Some user-defined type for which old values shall not be copied.
11fdf7f2
TL
140
141namespace boost { namespace contract {
92f5a8d4 142 template<> // Specialization to not copy old values of type `u`.
11fdf7f2
TL
143 struct is_old_value_copyable<u> : boost::false_type {};
144} } // namespace
145@endcode
146
92f5a8d4 147A given old value type @c T is copied only if
11fdf7f2 148@c boost::contract::is_old_value_copyable<T>::value is @c true.
92f5a8d4
TL
149A copyable old value type @c V is always copied using
150@c boost::contract::old_value_copy<V>.
151A non-copyable old value type @c W generates a compile-time error when
152@c boost::contract::old_ptr<W> is dereferenced, but instead leaves
153@c boost::contract::old_ptr_if_copyable<W> always null (without generating
11fdf7f2
TL
154compile-time errors).
155
156@see @RefSect{extras.old_value_requirements__templates_,
157 Old Value Requirements}
158*/
159template<typename T>
160struct is_old_value_copyable : boost::is_copy_constructible<T> {};
161
162/** @cond */
163class old_value;
164
165template<> // Needed because `old_value` incomplete type when trait first used.
166struct is_old_value_copyable<old_value> : boost::true_type {};
167/** @endcond */
168
169/**
170Trait to copy an old value.
171
172By default, the implementation of this trait uses @c T's copy constructor to
92f5a8d4 173make one single copy of the specified value.
11fdf7f2
TL
174However, programmers can specialize this trait to copy old values using
175user-specific operations different from @c T's copy constructor.
176The default implementation of this trait is equivalent to:
177
178@code
179template<typename T>
180class old_value_copy {
181public:
182 explicit old_value_copy(T const& old) :
92f5a8d4 183 old_(old) // One single copy of value using T's copy constructor.
11fdf7f2
TL
184 {}
185
186 T const& old() const { return old_; }
187
188private:
189 T const old_; // The old value copy.
190};
191@endcode
192
193This library will instantiate and use this trait only on old value types @c T
194that are copyable (i.e., for which
195<c>boost::contract::is_old_value_copyable<T>::value</c> is @c true).
196
197@see @RefSect{extras.old_value_requirements__templates_,
198 Old Value Requirements}
199*/
200template<typename T> // Used only if is_old_value_copyable<T>.
201struct old_value_copy {
202 /**
203 Construct this object by making one single copy of the specified old value.
204
205 This is the only operation within this library that actually copies old
206 values.
92f5a8d4
TL
207 This ensures this library makes one and only one copy of an old value (if
208 they actually need to be copied, see @RefMacro{BOOST_CONTRACT_NO_OLDS}).
11fdf7f2
TL
209
210 @param old The old value to copy.
211 */
212 explicit old_value_copy(T const& old) :
213 old_(old) {} // This makes the one single copy of T.
214
215 /**
216 Return a (constant) reference to the old value that was copied.
217
218 Contract assertions should not change the state of the program so the old
219 value copy is returned as @c const (see
220 @RefSect{contract_programming_overview.constant_correctness,
221 Constant Correctness}).
222 */
223 T const& old() const { return old_; }
224
225private:
226 T const old_;
227};
228
229template<typename T>
230class old_ptr_if_copyable;
231
232/**
233Old value pointer that requires the pointed old value type to be copyable.
234
92f5a8d4 235This pointer can be set to point an actual old value copy using either
11fdf7f2
TL
236@RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old} (that is
237why this class does not have public non-default constructors):
238
239@code
240class u {
241public:
242 virtual void f(..., boost::contract::virtual_* v = 0) {
92f5a8d4 243 boost::contract::old_ptr<old_type> old_var = // For copyable `old_type`.
11fdf7f2
TL
244 BOOST_CONTRACT_OLDOF(v, old_expr);
245 ...
246 }
247
248 ...
249};
250@endcode
251
252@see @RefSect{tutorial.old_values, Old Values}
253
254@tparam T Type of the pointed old value.
255 This type must be copyable (i.e.,
92f5a8d4
TL
256 <c>boost::contract::is_old_value_copyable<T>::value</c> must be
257 @c true), otherwise this pointer will always be null and this library
258 will generate a compile-time error when the pointer is dereferenced.
11fdf7f2
TL
259*/
260template<typename T>
261class old_ptr { /* copyable (as *) */
262public:
263 /** Pointed old value type. */
264 typedef T element_type;
265
266 /** Construct this old value pointer as null. */
267 old_ptr() {}
268
269 /**
270 Dereference this old value pointer.
271
272 This will generate a run-time error if this pointer is null and a
273 compile-time error if the pointed type @c T is not copyable (i.e., if
274 @c boost::contract::is_old_value_copyable<T>::value is @c false).
275
276 @return The pointed old value.
277 Contract assertions should not change the state of the program so
278 this member function is @c const and it returns the old value as a
279 reference to a constant object (see
280 @RefSect{contract_programming_overview.constant_correctness,
281 Constant Correctness}).
282 */
283 T const& operator*() const {
284 BOOST_STATIC_ASSERT_MSG(
285 boost::contract::is_old_value_copyable<T>::value,
286 "old_ptr<T> requires T copyable (see is_old_value_copyable<T>), "
287 "otherwise use old_ptr_if_copyable<T>"
288 );
289 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
290 return typed_copy_->old();
291 }
292
293 /**
294 Structure-dereference this old value pointer.
295
296 This will generate a compile-time error if the pointed type @c T is not
297 copyable (i.e., if @c boost::contract::is_old_value_copyable<T>::value is
298 @c false).
299
300 @return A pointer to the old value (null if this old value pointer is null).
301 Contract assertions should not change the state of the program so
302 this member function is @c const and it returns the old value as a
92f5a8d4 303 pointer to a constant object (see
11fdf7f2
TL
304 @RefSect{contract_programming_overview.constant_correctness,
305 Constant Correctness}).
306 */
92f5a8d4 307 T const* operator->() const {
11fdf7f2
TL
308 BOOST_STATIC_ASSERT_MSG(
309 boost::contract::is_old_value_copyable<T>::value,
310 "old_ptr<T> requires T copyble (see is_old_value_copyable<T>), "
311 "otherwise use old_ptr_if_copyable<T>"
312 );
313 if(typed_copy_) return &typed_copy_->old();
314 return 0;
315 }
316
317 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
318 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr<T>,
319 !!typed_copy_)
320 #else
321 /**
92f5a8d4 322 Query if this old value pointer is null or not (safe-bool operator).
11fdf7f2
TL
323
324 (This is implemented using safe-bool emulation on compilers that do not
325 support C++11 explicit type conversion operators.)
326
327 @return True if this pointer is not null, false otherwise.
328 */
329 explicit operator bool() const;
330 #endif
331
332/** @cond */
333private:
334 #ifndef BOOST_CONTRACT_NO_OLDS
335 explicit old_ptr(boost::shared_ptr<old_value_copy<T> > old)
336 : typed_copy_(old) {}
337 #endif
338
339 boost::shared_ptr<old_value_copy<T> > typed_copy_;
340
341 friend class old_pointer;
342 friend class old_ptr_if_copyable<T>;
343/** @endcond */
344};
345
346/**
347Old value pointer that does not require the pointed old value type to be
348copyable.
349
92f5a8d4 350This pointer can be set to point to an actual old value copy using either
11fdf7f2
TL
351@RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old}:
352
353@code
354template<typename T> // Type `T` might or not be copyable.
355class u {
356public:
357 virtual void f(..., boost::contract::virtual_* v = 0) {
358 boost::contract::old_ptr_if_copyable<T> old_var =
359 BOOST_CONTRACT_OLDOF(v, old_expr);
360 ...
361 if(old_var) ... // Always null for non-copyable types.
362 ...
363 }
364
365 ...
366};
367@endcode
368
369@see @RefSect{extras.old_value_requirements__templates_,
370 Old Value Requirements}
371
372@tparam T Type of the pointed old value.
373 If this type is not copyable (i.e.,
374 <c>boost::contract::is_old_value_copyable<T>::value</c> is @c false),
375 this pointer will always be null (but this library will not generate a
376 compile-time error when this pointer is dereferenced).
377*/
378template<typename T>
379class old_ptr_if_copyable { /* copyable (as *) */
380public:
381 /** Pointed old value type. */
382 typedef T element_type;
383
384 /** Construct this old value pointer as null. */
385 old_ptr_if_copyable() {}
386
387 /**
388 Construct this old value pointer from an old value pointer that requires
389 the old value type to be copyable.
92f5a8d4
TL
390
391 Ownership of the pointed value object is transferred to this pointer.
11fdf7f2
TL
392 This constructor is implicitly called by this library when assigning an
393 object of this type using @RefMacro{BOOST_CONTRACT_OLDOF} (this constructor
394 is usually not explicitly called by user code).
395
396 @param other Old value pointer that requires the old value type to be
397 copyable.
398 */
399 /* implicit */ old_ptr_if_copyable(old_ptr<T> const& other) :
400 typed_copy_(other.typed_copy_) {}
401
402 /**
403 Dereference this old value pointer.
404
405 This will generate a run-time error if this pointer is null, but no
406 compile-time error is generated if the pointed type @c T is not copyable
407 (i.e., if @c boost::contract::is_old_value_copyable<T>::value is @c false).
408
409 @return The pointed old value.
410 Contract assertions should not change the state of the program so
411 this member function is @c const and it returns the old value as a
412 reference to a constant object (see
413 @RefSect{contract_programming_overview.constant_correctness,
414 Constant Correctness}).
415 */
416 T const& operator*() const {
417 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
418 return typed_copy_->old();
419 }
420
421 /**
422 Structure-dereference this old value pointer.
423
424 This will return null but will not generate a compile-time error if the
425 pointed type @c T is not copyable (i.e., if
426 @c boost::contract::is_old_value_copyable<T>::value is @c false).
427
428 @return A pointer to the old value (null if this old value pointer is null).
429 Contract assertions should not change the state of the program so
430 this member function is @c const and it returns the old value as a
92f5a8d4 431 pointer to a constant object (see
11fdf7f2
TL
432 @RefSect{contract_programming_overview.constant_correctness,
433 Constant Correctness}).
434 */
92f5a8d4 435 T const* operator->() const {
11fdf7f2
TL
436 if(typed_copy_) return &typed_copy_->old();
437 return 0;
438 }
439
440 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
441 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_if_copyable<T>,
442 !!typed_copy_)
443 #else
444 /**
92f5a8d4 445 Query if this old value pointer is null or not (safe-bool operator).
11fdf7f2
TL
446
447 (This is implemented using safe-bool emulation on compilers that do not
448 support C++11 explicit type conversion operators.)
449
450 @return True if this pointer is not null, false otherwise.
451 */
452 explicit operator bool() const;
453 #endif
454
455/** @cond */
456private:
457 #ifndef BOOST_CONTRACT_NO_OLDS
458 explicit old_ptr_if_copyable(boost::shared_ptr<old_value_copy<T> > old)
459 : typed_copy_(old) {}
460 #endif
461
462 boost::shared_ptr<old_value_copy<T> > typed_copy_;
463
464 friend class old_pointer;
465/** @endcond */
466};
467
468/**
469Convert user-specified expressions to old values.
470
92f5a8d4 471This class is usually only implicitly used by this library and it does not
11fdf7f2
TL
472explicitly appear in user code.
473
474On older compilers that cannot correctly deduce the
92f5a8d4
TL
475@c boost::contract::is_old_value_copyable trait used in the declaration of this
476class, programmers can manually specialize that trait to make sure that only old
477value types that are copyable are actually copied.
11fdf7f2
TL
478
479@see @RefSect{extras.old_value_requirements__templates_,
480 Old Value Requirements}
481*/
482class old_value { // Copyable (as *).
483public:
484 // Following implicitly called by ternary operator `... ? ... : null_old()`.
485
486 /**
487 Construct this object from the specified old value when the old value type
488 is copy constructible.
489
92f5a8d4
TL
490 The specified old value @c old is copied (one time only) using
491 @c boost::contract::old_value_copy, in which case the related old value
492 pointer will not be null (but no copy is made if postconditions and
493 exception guarantees are not being checked, see
494 @RefMacro{BOOST_CONTRACT_NO_OLDS}).
11fdf7f2
TL
495
496 @param old Old value to be copied.
497
498 @tparam T Old value type.
499 */
500 template<typename T>
501 /* implicit */ old_value(
92f5a8d4
TL
502 T const&
503 #if !defined(BOOST_CONTRACT_NO_OLDS) || \
504 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
505 old
506 #endif // Else, no name (avoid unused param warning).
507 ,
11fdf7f2
TL
508 typename boost::enable_if<boost::contract::is_old_value_copyable<T>
509 >::type* = 0
510 )
511 #ifndef BOOST_CONTRACT_NO_OLDS
512 : untyped_copy_(new old_value_copy<T>(old))
513 #endif // Else, leave ptr_ null (thus no copy of T).
514 {}
515
516 /**
517 Construct this object from the specified old value when the old value type
518 is not copyable.
519
92f5a8d4
TL
520 The specified old value @c old cannot be copied in this case so it is not
521 copied and the related old value pointer will always be null (thus calls to
522 this constructor have no effect and they will likely be optimized away by
523 most compilers).
11fdf7f2
TL
524
525 @param old Old value (that will not be copied in this case).
526
527 @tparam T Old value type.
528 */
529 template<typename T>
530 /* implicit */ old_value(
92f5a8d4
TL
531 T const&
532 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
533 old
534 #endif // Else, no name (avoid unused param warning).
535 ,
11fdf7f2
TL
536 typename boost::disable_if<boost::contract::is_old_value_copyable<T>
537 >::type* = 0
538 ) {} // Leave ptr_ null (thus no copy of T).
539
540/** @cond */
541private:
542 explicit old_value() {}
543
544 #ifndef BOOST_CONTRACT_NO_OLDS
545 boost::shared_ptr<void> untyped_copy_; // Type erasure.
546 #endif
547
548 friend class old_pointer;
549 friend BOOST_CONTRACT_DETAIL_DECLSPEC old_value null_old();
550/** @endcond */
551};
552
553/**
92f5a8d4 554Convert old value copies into old value pointers.
11fdf7f2 555
92f5a8d4 556This class is usually only implicitly used by this library and it does not
11fdf7f2
TL
557explicitly appear in user code (that is why this class does not have public
558constructors, etc.).
559*/
560class old_pointer { // Copyable (as *).
561public:
562 /**
563 Convert this object to an actual old value pointer for which the old value
564 type @c T might or not be copyable.
565
566 For example, this is implicitly called when assigning or initializing old
92f5a8d4 567 value pointers of type @c boost::contract::old_ptr_if_copyable.
11fdf7f2
TL
568
569 @tparam T Type of the pointed old value.
570 The old value pointer will always be null if this type is not
571 copyable (see
572 @c boost::contract::is_old_value_copyable), but this library
573 will not generate a compile-time error.
574 */
575 template<typename T>
576 /* implicit */ operator old_ptr_if_copyable<T>() {
577 return get<old_ptr_if_copyable<T> >();
578 }
579
580 /**
581 Convert this object to an actual old value pointer for which the old value
582 type @c T must be copyable.
583
584 For example, this is implicitly called when assigning or initializing old
92f5a8d4 585 value pointers of type @c boost::contract::old_ptr.
11fdf7f2
TL
586
587 @tparam T Type of the pointed old value. This type must be copyable
588 (see @c boost::contract::is_old_value_copyable),
589 otherwise this library will generate a compile-time error when
590 the old value pointer is dereferenced.
591 */
592 template<typename T>
593 /* implicit */ operator old_ptr<T>() {
594 return get<old_ptr<T> >();
595 }
596
597/** @cond */
598private:
92f5a8d4
TL
599 #ifndef BOOST_CONTRACT_NO_OLDS
600 explicit old_pointer(virtual_* v, old_value const& old)
601 : v_(v), untyped_copy_(old.untyped_copy_) {}
602 #else
603 explicit old_pointer(virtual_* /* v */, old_value const& /* old */) {}
604 #endif
11fdf7f2
TL
605
606 template<typename Ptr>
607 Ptr get() {
608 #ifndef BOOST_CONTRACT_NO_OLDS
609 if(!boost::contract::is_old_value_copyable<typename
610 Ptr::element_type>::value) {
611 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
612 return Ptr(); // Non-copyable so no old value and return null.
613 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
614 } else if(!v_ && boost::contract::detail::checking::already()) {
615 return Ptr(); // Not checking (so return null).
616 #endif
617 } else if(!v_) {
618 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy_);
619 typedef old_value_copy<typename Ptr::element_type> copied_type;
620 boost::shared_ptr<copied_type> typed_copy = // Un-erase type.
621 boost::static_pointer_cast<copied_type>(untyped_copy_);
622 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy);
623 return Ptr(typed_copy);
624 } else if(
625 v_->action_ == boost::contract::virtual_::push_old_init_copy ||
626 v_->action_ == boost::contract::virtual_::push_old_ftor_copy
627 ) {
628 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy_);
629 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
630 boost::contract::virtual_::push_old_ftor_copy ?
631 v_->old_ftor_copies_
632 :
633 v_->old_init_copies_
634 ;
635 copies.push(untyped_copy_);
636 return Ptr(); // Pushed (so return null).
637 } else if(
638 boost::contract::virtual_::pop_old_init_copy(v_->action_) ||
639 v_->action_ == boost::contract::virtual_::pop_old_ftor_copy
640 ) {
641 // Copy not null, but still pop it from the queue.
642 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
643
644 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
645 boost::contract::virtual_::pop_old_ftor_copy ?
646 v_->old_ftor_copies_
647 :
648 v_->old_init_copies_
649 ;
650 boost::shared_ptr<void> untyped_copy = copies.front();
651 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy);
652 copies.pop();
653
654 typedef old_value_copy<typename Ptr::element_type> copied_type;
655 boost::shared_ptr<copied_type> typed_copy = // Un-erase type.
656 boost::static_pointer_cast<copied_type>(untyped_copy);
657 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy);
658 return Ptr(typed_copy);
659 }
660 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
661 #endif
662 return Ptr();
663 }
664
665 #ifndef BOOST_CONTRACT_NO_OLDS
666 virtual_* v_;
667 boost::shared_ptr<void> untyped_copy_; // Type erasure.
668 #endif
669
670 friend BOOST_CONTRACT_DETAIL_DECLSPEC
671 old_pointer make_old(old_value const&);
672
673 friend BOOST_CONTRACT_DETAIL_DECLSPEC
674 old_pointer make_old(virtual_*, old_value const&);
675/** @endcond */
676};
677
678/**
92f5a8d4 679Return a "null" old value.
11fdf7f2
TL
680
681The related old value pointer will also be null.
92f5a8d4 682This function is usually only called by the code expanded by
11fdf7f2
TL
683@RefMacro{BOOST_CONTRACT_OLDOF}.
684
685@see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
686
687@return Null old value.
688*/
689/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
690old_value null_old();
691
692/**
693Make an old value pointer (but not for virtual public functions and public
694functions overrides).
695
696The related old value pointer will not be null if the specified old value was
697actually copied.
92f5a8d4
TL
698This function is usually only called by code expanded by
699@c BOOST_CONTRACT_OLDOF(old_expr) as in:
11fdf7f2
TL
700
701@code
702boost::contract::make_old(boost::contract::copy_old() ? old_expr :
703 boost::contract::null_old())
704@endcode
705
706@see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
707
708@param old Old value which is usually implicitly constructed from the user old
709 value expression to be copied (use the ternary operator <c>?:</c>
92f5a8d4 710 to completely avoid to evaluate the old value expression when
11fdf7f2
TL
711 @c boost::contract::copy_old() is @c false).
712
713@return Old value pointer (usually implicitly converted to either
714 @RefClass{boost::contract::old_ptr} or
715 @RefClass{boost::contract::old_ptr_if_copyable} in user code).
716*/
717/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
718old_pointer make_old(old_value const& old);
719
720/**
721Make an old value pointer (for virtual public functions and public functions
722overrides).
723
724The related old value pointer will not be null if the specified old value was
725actually copied.
92f5a8d4
TL
726This function is usually only called by code expanded by
727@c BOOST_CONTRACT_OLDOF(v, old_expr) as in:
11fdf7f2
TL
728
729@code
730boost::contract::make_old(v, boost::contract::copy_old(v) ? old_expr :
731 boost::contract::null_old())
732@endcode
733
734@see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
735
736@param v The trailing parameter of type
737 @RefClass{boost::contract::virtual_}<c>*</c> and default value @c 0
738 from the enclosing virtual or overriding public function declaring
739 the contract.
740@param old Old value which is usually implicitly constructed from the user old
741 value expression to be copied (use the ternary operator <c>?:</c>
92f5a8d4 742 to completely avoid to evaluate the old value expression when
11fdf7f2
TL
743 @c boost::contract::copy_old(v) is @c false).
744
745@return Old value pointer (usually implicitly converted to either
746 @RefClass{boost::contract::old_ptr} or
747 @RefClass{boost::contract::old_ptr_if_copyable} in user code).
748*/
749/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
750old_pointer make_old(virtual_* v, old_value const& old);
751
752/**
92f5a8d4 753Query if old values need to be copied (but not for virtual public functions and
11fdf7f2
TL
754public function overrides).
755
756For example, this function always returns false when both postconditions and
757exception guarantees are not being checked (see
758@RefMacro{BOOST_CONTRACT_NO_OLDS}).
92f5a8d4 759This function is usually only called by the code expanded by
11fdf7f2
TL
760@RefMacro{BOOST_CONTRACT_OLDOF}.
761
762@see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
763
764@return True if old values need to be copied, false otherwise.
765*/
766inline bool copy_old() {
767 #ifndef BOOST_CONTRACT_NO_OLDS
768 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
769 return !boost::contract::detail::checking::already();
770 #else
771 return true;
772 #endif
773 #else
774 return false; // No post checking, so never copy old values.
775 #endif
776}
777
778/**
92f5a8d4 779Query if old values need to be copied (for virtual public functions and public
11fdf7f2
TL
780function overrides).
781
782For example, this function always returns false when both postconditions and
783exception guarantees are not being checked (see
784@RefMacro{BOOST_CONTRACT_NO_OLDS}).
785In addition, this function returns false when overridden functions are being
786called subsequent times by this library to support subcontracting.
92f5a8d4 787This function is usually only called by the code expanded by
11fdf7f2
TL
788@RefMacro{BOOST_CONTRACT_OLDOF}.
789
790@see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
791
792@param v The trailing parameter of type
793 @RefClass{boost::contract::virtual_}<c>*</c> and default value @c 0
794 from the enclosing virtual or overriding public function declaring
795 the contract.
796
797@return True if old values need to be copied, false otherwise.
798*/
92f5a8d4
TL
799#ifndef BOOST_CONTRACT_NO_OLDS
800 inline bool copy_old(virtual_* v) {
11fdf7f2
TL
801 if(!v) {
802 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
803 return !boost::contract::detail::checking::already();
804 #else
805 return true;
806 #endif
807 }
808 return v->action_ == boost::contract::virtual_::push_old_init_copy ||
809 v->action_ == boost::contract::virtual_::push_old_ftor_copy;
92f5a8d4
TL
810 }
811#else
812 inline bool copy_old(virtual_*
813 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
814 v
815 #endif
816 ) {
11fdf7f2 817 return false; // No post checking, so never copy old values.
92f5a8d4
TL
818 }
819#endif
11fdf7f2
TL
820
821} } // namespace
822
823#ifdef BOOST_CONTRACT_HEADER_ONLY
824 #include <boost/contract/detail/inlined/old.hpp>
825#endif
826
827#endif // #include guard
828