]> git.proxmox.com Git - ceph.git/blob - 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
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
11 Handle 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 \
34 BOOST_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 /**
74 Macro typically used to copy an old value expression and assign it to an old
75 value pointer.
76
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
81 different ways.
82
83 1\. From within virtual public functions and public functions overrides:
84
85 @code
86 BOOST_CONTRACT_OLDOF(v, old_expr)
87 @endcode
88
89 2\. From all other operations:
90
91 @code
92 BOOST_CONTRACT_OLDOF(old_expr)
93 @endcode
94
95 Where:
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.
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.)
106
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}).
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
126 namespace boost { namespace contract {
127
128 /**
129 Trait to check if an old value type can be copied or not.
130
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>):
137
138 @code
139 class u; // Some user-defined type for which old values shall not be copied.
140
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 {};
144 } } // namespace
145 @endcode
146
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).
155
156 @see @RefSect{extras.old_value_requirements__templates_,
157 Old Value Requirements}
158 */
159 template<typename T>
160 struct is_old_value_copyable : boost::is_copy_constructible<T> {};
161
162 /** @cond */
163 class old_value;
164
165 template<> // Needed because `old_value` incomplete type when trait first used.
166 struct is_old_value_copyable<old_value> : boost::true_type {};
167 /** @endcond */
168
169 /**
170 Trait to copy an old value.
171
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:
177
178 @code
179 template<typename T>
180 class old_value_copy {
181 public:
182 explicit old_value_copy(T const& old) :
183 old_(old) // One single copy of value using T's copy constructor.
184 {}
185
186 T const& old() const { return old_; }
187
188 private:
189 T const old_; // The old value copy.
190 };
191 @endcode
192
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).
196
197 @see @RefSect{extras.old_value_requirements__templates_,
198 Old Value Requirements}
199 */
200 template<typename T> // Used only if is_old_value_copyable<T>.
201 struct 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.
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}).
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
225 private:
226 T const old_;
227 };
228
229 template<typename T>
230 class old_ptr_if_copyable;
231
232 /**
233 Old value pointer that requires the pointed old value type to be copyable.
234
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):
238
239 @code
240 class u {
241 public:
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);
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.,
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.
259 */
260 template<typename T>
261 class old_ptr { /* copyable (as *) */
262 public:
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
303 pointer to a constant object (see
304 @RefSect{contract_programming_overview.constant_correctness,
305 Constant Correctness}).
306 */
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>"
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 /**
322 Query if this old value pointer is null or not (safe-bool operator).
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 */
333 private:
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 /**
347 Old value pointer that does not require the pointed old value type to be
348 copyable.
349
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}:
352
353 @code
354 template<typename T> // Type `T` might or not be copyable.
355 class u {
356 public:
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 */
378 template<typename T>
379 class old_ptr_if_copyable { /* copyable (as *) */
380 public:
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.
390
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).
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
431 pointer to a constant object (see
432 @RefSect{contract_programming_overview.constant_correctness,
433 Constant Correctness}).
434 */
435 T const* operator->() const {
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 /**
445 Query if this old value pointer is null or not (safe-bool operator).
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 */
456 private:
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 /**
469 Convert user-specified expressions to old values.
470
471 This class is usually only implicitly used by this library and it does not
472 explicitly appear in user code.
473
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.
478
479 @see @RefSect{extras.old_value_requirements__templates_,
480 Old Value Requirements}
481 */
482 class old_value { // Copyable (as *).
483 public:
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
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}).
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(
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 ,
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
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).
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(
531 T const&
532 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
533 old
534 #endif // Else, no name (avoid unused param warning).
535 ,
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 */
541 private:
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 /**
554 Convert old value copies into old value pointers.
555
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
558 constructors, etc.).
559 */
560 class old_pointer { // Copyable (as *).
561 public:
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
567 value pointers of type @c boost::contract::old_ptr_if_copyable.
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
585 value pointers of type @c boost::contract::old_ptr.
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 */
598 private:
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
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 /**
679 Return a "null" old value.
680
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}.
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 */
690 old_value null_old();
691
692 /**
693 Make an old value pointer (but not for virtual public functions and public
694 functions overrides).
695
696 The related old value pointer will not be null if the specified old value was
697 actually copied.
698 This function is usually only called by code expanded by
699 @c BOOST_CONTRACT_OLDOF(old_expr) as in:
700
701 @code
702 boost::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>
710 to completely avoid to evaluate the old value expression when
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 */
718 old_pointer make_old(old_value const& old);
719
720 /**
721 Make an old value pointer (for virtual public functions and public functions
722 overrides).
723
724 The related old value pointer will not be null if the specified old value was
725 actually copied.
726 This function is usually only called by code expanded by
727 @c BOOST_CONTRACT_OLDOF(v, old_expr) as in:
728
729 @code
730 boost::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>
742 to completely avoid to evaluate the old value expression when
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 */
750 old_pointer make_old(virtual_* v, old_value const& old);
751
752 /**
753 Query if old values need to be copied (but not for virtual public functions and
754 public function overrides).
755
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}.
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 */
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();
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 /**
779 Query if old values need to be copied (for virtual public functions and public
780 function overrides).
781
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}.
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 */
799 #ifndef BOOST_CONTRACT_NO_OLDS
800 inline bool copy_old(virtual_* v) {
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;
810 }
811 #else
812 inline bool copy_old(virtual_*
813 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN
814 v
815 #endif
816 ) {
817 return false; // No post checking, so never copy old values.
818 }
819 #endif
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