2 #ifndef BOOST_CONTRACT_OLD_HPP_
3 #define BOOST_CONTRACT_OLD_HPP_
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
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>
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>
31 #if !BOOST_PP_VARIADICS
33 #define BOOST_CONTRACT_OLDOF \
34 BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_program_old_values
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>
47 #ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
48 #define BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value) /* nothing */
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)>
56 #define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_2( \
58 BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value)(boost::contract::make_old(v, \
59 boost::contract::copy_old(v) ? (value) : boost::contract::null_old() \
62 #define BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_1( \
64 BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value)(boost::contract::make_old( \
65 boost::contract::copy_old() ? (value) : boost::contract::null_old() \
72 // NOTE: Leave this #defined the same regardless of ..._NO_OLDS.
74 Macro typically used to copy an old value expression and assign it to an old
77 The expression expanded by this macro should be assigned to an old value
78 pointer of type @RefClass{boost::contract::old_ptr} or
79 @RefClass{boost::contract::old_ptr_if_copyable}.
80 This is an overloaded variadic macro and it can be used in the following
83 1\. From within virtual public functions and public functions overrides:
86 BOOST_CONTRACT_OLDOF(v, old_expr)
89 2\. From all other operations:
92 BOOST_CONTRACT_OLDOF(old_expr)
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.
101 @arg <c><b>old_expr</b></c> is the expression to be evaluated and copied into
102 the old value pointer.
103 (This is not a variadic macro parameter so any comma it might contain
104 must be protected by round parenthesis and
105 <c>BOOST_CONTRACT_OLDOF(v, (old_expr))</c> will always work.)
107 On compilers that do not support variadic macros, programmers can manually copy
108 old value expressions without using this macro (see
109 @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}).
111 @see @RefSect{tutorial.old_values, Old Values}
113 #define BOOST_CONTRACT_OLDOF(...) \
114 BOOST_PP_CAT( /* CAT(..., EMTPY()) required on MSVC */ \
116 BOOST_CONTRACT_ERROR_macro_OLDOF_has_invalid_number_of_arguments_, \
126 namespace boost { namespace contract {
129 Trait to check if an old value type can be copied or not.
131 By default, this unary boolean meta-function is equivalent to
132 @c boost::is_copy_constructible<T> but programmers can chose to specialize it
133 for user-defined types (in general some kind of specialization is also needed on
134 compilers 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>):
139 class u; // Some user-defined type for which old values shall not be copied.
141 namespace boost { namespace contract {
142 template<> // Specialization to not copy old values of type `u`.
143 struct is_old_value_copyable<u> : boost::false_type {};
147 A given old value type @c T is copied only if
148 @c boost::contract::is_old_value_copyable<T>::value is @c true.
149 A copyable old value type @c V is always copied using
150 @c boost::contract::old_value_copy<V>.
151 A 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
154 compile-time errors).
156 @see @RefSect{extras.old_value_requirements__templates_,
157 Old Value Requirements}
160 struct is_old_value_copyable : boost::is_copy_constructible<T> {};
165 template<> // Needed because `old_value` incomplete type when trait first used.
166 struct is_old_value_copyable<old_value> : boost::true_type {};
170 Trait to copy an old value.
172 By default, the implementation of this trait uses @c T's copy constructor to
173 make one single copy of the specified value.
174 However, programmers can specialize this trait to copy old values using
175 user-specific operations different from @c T's copy constructor.
176 The default implementation of this trait is equivalent to:
180 class old_value_copy {
182 explicit old_value_copy(T const& old) :
183 old_(old) // One single copy of value using T's copy constructor.
186 T const& old() const { return old_; }
189 T const old_; // The old value copy.
193 This library will instantiate and use this trait only on old value types @c T
194 that are copyable (i.e., for which
195 <c>boost::contract::is_old_value_copyable<T>::value</c> is @c true).
197 @see @RefSect{extras.old_value_requirements__templates_,
198 Old Value Requirements}
200 template<typename T> // Used only if is_old_value_copyable<T>.
201 struct old_value_copy {
203 Construct this object by making one single copy of the specified old value.
205 This is the only operation within this library that actually copies old
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}).
210 @param old The old value to copy.
212 explicit old_value_copy(T const& old) :
213 old_(old) {} // This makes the one single copy of T.
216 Return a (constant) reference to the old value that was copied.
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}).
223 T const& old() const { return old_; }
230 class old_ptr_if_copyable;
233 Old value pointer that requires the pointed old value type to be copyable.
235 This pointer can be set to point an actual old value copy using either
236 @RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old} (that is
237 why this class does not have public non-default constructors):
242 virtual void f(..., boost::contract::virtual_* v = 0) {
243 boost::contract::old_ptr<old_type> old_var = // For copyable `old_type`.
244 BOOST_CONTRACT_OLDOF(v, old_expr);
252 @see @RefSect{tutorial.old_values, Old Values}
254 @tparam T Type of the pointed old value.
255 This type must be copyable (i.e.,
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.
261 class old_ptr { /* copyable (as *) */
263 /** Pointed old value type. */
264 typedef T element_type;
266 /** Construct this old value pointer as null. */
270 Dereference this old value pointer.
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).
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}).
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>"
289 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
290 return typed_copy_->old();
294 Structure-dereference this old value pointer.
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
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
303 pointer to a constant object (see
304 @RefSect{contract_programming_overview.constant_correctness,
305 Constant Correctness}).
307 T const* operator->() const {
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>"
313 if(typed_copy_) return &typed_copy_->old();
317 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
318 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr<T>,
322 Query if this old value pointer is null or not (safe-bool operator).
324 (This is implemented using safe-bool emulation on compilers that do not
325 support C++11 explicit type conversion operators.)
327 @return True if this pointer is not null, false otherwise.
329 explicit operator bool() const;
334 #ifndef BOOST_CONTRACT_NO_OLDS
335 explicit old_ptr(boost::shared_ptr<old_value_copy<T> > old)
336 : typed_copy_(old) {}
339 boost::shared_ptr<old_value_copy<T> > typed_copy_;
341 friend class old_pointer;
342 friend class old_ptr_if_copyable<T>;
347 Old value pointer that does not require the pointed old value type to be
350 This pointer can be set to point to an actual old value copy using either
351 @RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old}:
354 template<typename T> // Type `T` might or not be copyable.
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);
361 if(old_var) ... // Always null for non-copyable types.
369 @see @RefSect{extras.old_value_requirements__templates_,
370 Old Value Requirements}
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).
379 class old_ptr_if_copyable { /* copyable (as *) */
381 /** Pointed old value type. */
382 typedef T element_type;
384 /** Construct this old value pointer as null. */
385 old_ptr_if_copyable() {}
388 Construct this old value pointer from an old value pointer that requires
389 the old value type to be copyable.
391 Ownership of the pointed value object is transferred to this pointer.
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).
396 @param other Old value pointer that requires the old value type to be
399 /* implicit */ old_ptr_if_copyable(old_ptr<T> const& other) :
400 typed_copy_(other.typed_copy_) {}
403 Dereference this old value pointer.
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).
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}).
416 T const& operator*() const {
417 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
418 return typed_copy_->old();
422 Structure-dereference this old value pointer.
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).
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
431 pointer to a constant object (see
432 @RefSect{contract_programming_overview.constant_correctness,
433 Constant Correctness}).
435 T const* operator->() const {
436 if(typed_copy_) return &typed_copy_->old();
440 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
441 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_if_copyable<T>,
445 Query if this old value pointer is null or not (safe-bool operator).
447 (This is implemented using safe-bool emulation on compilers that do not
448 support C++11 explicit type conversion operators.)
450 @return True if this pointer is not null, false otherwise.
452 explicit operator bool() const;
457 #ifndef BOOST_CONTRACT_NO_OLDS
458 explicit old_ptr_if_copyable(boost::shared_ptr<old_value_copy<T> > old)
459 : typed_copy_(old) {}
462 boost::shared_ptr<old_value_copy<T> > typed_copy_;
464 friend class old_pointer;
469 Convert user-specified expressions to old values.
471 This class is usually only implicitly used by this library and it does not
472 explicitly appear in user code.
474 On older compilers that cannot correctly deduce the
475 @c boost::contract::is_old_value_copyable trait used in the declaration of this
476 class, programmers can manually specialize that trait to make sure that only old
477 value types that are copyable are actually copied.
479 @see @RefSect{extras.old_value_requirements__templates_,
480 Old Value Requirements}
482 class old_value { // Copyable (as *).
484 // Following implicitly called by ternary operator `... ? ... : null_old()`.
487 Construct this object from the specified old value when the old value type
488 is copy constructible.
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}).
496 @param old Old value to be copied.
498 @tparam T Old value type.
501 /* implicit */ old_value(
503 #if !defined(BOOST_CONTRACT_NO_OLDS) || \
504 defined(BOOST_CONTRACT_DETAIL_DOXYGEN)
506 #endif // Else, no name (avoid unused param warning).
508 typename boost::enable_if<boost::contract::is_old_value_copyable<T>
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).
517 Construct this object from the specified old value when the old value type
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
525 @param old Old value (that will not be copied in this case).
527 @tparam T Old value type.
530 /* implicit */ old_value(
532 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
534 #endif // Else, no name (avoid unused param warning).
536 typename boost::disable_if<boost::contract::is_old_value_copyable<T>
538 ) {} // Leave ptr_ null (thus no copy of T).
542 explicit old_value() {}
544 #ifndef BOOST_CONTRACT_NO_OLDS
545 boost::shared_ptr<void> untyped_copy_; // Type erasure.
548 friend class old_pointer;
549 friend BOOST_CONTRACT_DETAIL_DECLSPEC old_value null_old();
554 Convert old value copies into old value pointers.
556 This class is usually only implicitly used by this library and it does not
557 explicitly appear in user code (that is why this class does not have public
560 class old_pointer { // Copyable (as *).
563 Convert this object to an actual old value pointer for which the old value
564 type @c T might or not be copyable.
566 For example, this is implicitly called when assigning or initializing old
567 value pointers of type @c boost::contract::old_ptr_if_copyable.
569 @tparam T Type of the pointed old value.
570 The old value pointer will always be null if this type is not
572 @c boost::contract::is_old_value_copyable), but this library
573 will not generate a compile-time error.
576 /* implicit */ operator old_ptr_if_copyable<T>() {
577 return get<old_ptr_if_copyable<T> >();
581 Convert this object to an actual old value pointer for which the old value
582 type @c T must be copyable.
584 For example, this is implicitly called when assigning or initializing old
585 value pointers of type @c boost::contract::old_ptr.
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.
593 /* implicit */ operator old_ptr<T>() {
594 return get<old_ptr<T> >();
599 #ifndef BOOST_CONTRACT_NO_OLDS
600 explicit old_pointer(virtual_* v, old_value const& old)
601 : v_(v), untyped_copy_(old.untyped_copy_) {}
603 explicit old_pointer(virtual_* /* v */, old_value const& /* old */) {}
606 template<typename Ptr>
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).
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);
625 v_->action_ == boost::contract::virtual_::push_old_init_copy ||
626 v_->action_ == boost::contract::virtual_::push_old_ftor_copy
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 ?
635 copies.push(untyped_copy_);
636 return Ptr(); // Pushed (so return null).
638 boost::contract::virtual_::pop_old_init_copy(v_->action_) ||
639 v_->action_ == boost::contract::virtual_::pop_old_ftor_copy
641 // Copy not null, but still pop it from the queue.
642 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
644 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
645 boost::contract::virtual_::pop_old_ftor_copy ?
650 boost::shared_ptr<void> untyped_copy = copies.front();
651 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy);
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);
660 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
665 #ifndef BOOST_CONTRACT_NO_OLDS
667 boost::shared_ptr<void> untyped_copy_; // Type erasure.
670 friend BOOST_CONTRACT_DETAIL_DECLSPEC
671 old_pointer make_old(old_value const&);
673 friend BOOST_CONTRACT_DETAIL_DECLSPEC
674 old_pointer make_old(virtual_*, old_value const&);
679 Return a "null" old value.
681 The related old value pointer will also be null.
682 This function is usually only called by the code expanded by
683 @RefMacro{BOOST_CONTRACT_OLDOF}.
685 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
687 @return Null old value.
689 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
690 old_value null_old();
693 Make an old value pointer (but not for virtual public functions and public
694 functions overrides).
696 The related old value pointer will not be null if the specified old value was
698 This function is usually only called by code expanded by
699 @c BOOST_CONTRACT_OLDOF(old_expr) as in:
702 boost::contract::make_old(boost::contract::copy_old() ? old_expr :
703 boost::contract::null_old())
706 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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>
710 to completely avoid to evaluate the old value expression when
711 @c boost::contract::copy_old() is @c false).
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).
717 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
718 old_pointer make_old(old_value const& old);
721 Make an old value pointer (for virtual public functions and public functions
724 The related old value pointer will not be null if the specified old value was
726 This function is usually only called by code expanded by
727 @c BOOST_CONTRACT_OLDOF(v, old_expr) as in:
730 boost::contract::make_old(v, boost::contract::copy_old(v) ? old_expr :
731 boost::contract::null_old())
734 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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
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>
742 to completely avoid to evaluate the old value expression when
743 @c boost::contract::copy_old(v) is @c false).
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).
749 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
750 old_pointer make_old(virtual_* v, old_value const& old);
753 Query if old values need to be copied (but not for virtual public functions and
754 public function overrides).
756 For example, this function always returns false when both postconditions and
757 exception guarantees are not being checked (see
758 @RefMacro{BOOST_CONTRACT_NO_OLDS}).
759 This function is usually only called by the code expanded by
760 @RefMacro{BOOST_CONTRACT_OLDOF}.
762 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
764 @return True if old values need to be copied, false otherwise.
766 inline bool copy_old() {
767 #ifndef BOOST_CONTRACT_NO_OLDS
768 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
769 return !boost::contract::detail::checking::already();
774 return false; // No post checking, so never copy old values.
779 Query if old values need to be copied (for virtual public functions and public
782 For example, this function always returns false when both postconditions and
783 exception guarantees are not being checked (see
784 @RefMacro{BOOST_CONTRACT_NO_OLDS}).
785 In addition, this function returns false when overridden functions are being
786 called subsequent times by this library to support subcontracting.
787 This function is usually only called by the code expanded by
788 @RefMacro{BOOST_CONTRACT_OLDOF}.
790 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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
797 @return True if old values need to be copied, false otherwise.
799 #ifndef BOOST_CONTRACT_NO_OLDS
800 inline bool copy_old(virtual_* v) {
802 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
803 return !boost::contract::detail::checking::already();
808 return v->action_ == boost::contract::virtual_::push_old_init_copy ||
809 v->action_ == boost::contract::virtual_::push_old_ftor_copy;
812 inline bool copy_old(virtual_*
813 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
817 return false; // No post checking, so never copy old values.
823 #ifdef BOOST_CONTRACT_HEADER_ONLY
824 #include <boost/contract/detail/inlined/old.hpp>
827 #endif // #include guard