]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/contract/old.hpp
update sources to ceph Nautilus 14.2.1
[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 to
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,
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 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.
140
141 namespace boost { namespace contract {
142 template<> // Specialization.
143 struct is_old_value_copyable<u> : boost::false_type {};
144 } } // namespace
145 @endcode
146
147 In summary, 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 Copyable old value types are always copied using
150 @c boost::contract::old_value_copy<T>.
151 Non-copyable old value types generate a compile-time error when
152 @c boost::contract::old_ptr<T> is dereferenced, but instead leave
153 @c boost::contract::old_ptr_if_copyable<T> 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 @p 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_(value) // 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 old values (if they
208 actually need to be copied).
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 is set to point to 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 =
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> is @c true),
257 otherwise this pointer will always be null and this library will
258 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 constant pointer to a constant object (see
304 @RefSect{contract_programming_overview.constant_correctness,
305 Constant Correctness}).
306 */
307 T const* 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 Check if this old value pointer is null or not.
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 is 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 This constructor is implicitly called by this library when assigning an
392 object of this type using @RefMacro{BOOST_CONTRACT_OLDOF} (this constructor
393 is usually not explicitly called by user code).
394
395 @param other Old value pointer that requires the old value type to be
396 copyable.
397 */
398 /* implicit */ old_ptr_if_copyable(old_ptr<T> const& other) :
399 typed_copy_(other.typed_copy_) {}
400
401 /**
402 Dereference this old value pointer.
403
404 This will generate a run-time error if this pointer is null, but no
405 compile-time error is generated if the pointed type @c T is not copyable
406 (i.e., if @c boost::contract::is_old_value_copyable<T>::value is @c false).
407
408 @return The pointed old value.
409 Contract assertions should not change the state of the program so
410 this member function is @c const and it returns the old value as a
411 reference to a constant object (see
412 @RefSect{contract_programming_overview.constant_correctness,
413 Constant Correctness}).
414 */
415 T const& operator*() const {
416 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
417 return typed_copy_->old();
418 }
419
420 /**
421 Structure-dereference this old value pointer.
422
423 This will return null but will not generate a compile-time error if the
424 pointed type @c T is not copyable (i.e., if
425 @c boost::contract::is_old_value_copyable<T>::value is @c false).
426
427 @return A pointer to the old value (null if this old value pointer is null).
428 Contract assertions should not change the state of the program so
429 this member function is @c const and it returns the old value as a
430 constant pointer to a constant object (see
431 @RefSect{contract_programming_overview.constant_correctness,
432 Constant Correctness}).
433 */
434 T const* const operator->() const {
435 if(typed_copy_) return &typed_copy_->old();
436 return 0;
437 }
438
439 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
440 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_if_copyable<T>,
441 !!typed_copy_)
442 #else
443 /**
444 Check if this old value pointer is null or not (safe-bool operator).
445
446 (This is implemented using safe-bool emulation on compilers that do not
447 support C++11 explicit type conversion operators.)
448
449 @return True if this pointer is not null, false otherwise.
450 */
451 explicit operator bool() const;
452 #endif
453
454 /** @cond */
455 private:
456 #ifndef BOOST_CONTRACT_NO_OLDS
457 explicit old_ptr_if_copyable(boost::shared_ptr<old_value_copy<T> > old)
458 : typed_copy_(old) {}
459 #endif
460
461 boost::shared_ptr<old_value_copy<T> > typed_copy_;
462
463 friend class old_pointer;
464 /** @endcond */
465 };
466
467 /**
468 Convert user-specified expressions to old values.
469
470 This class is often only implicitly used by this library and it does not
471 explicitly appear in user code.
472
473 On older compilers that cannot correctly deduce the
474 @c boost::contract::is_old_value_copyable trait, programmers can manually
475 specialize that trait to make sure that only old value types that are copyable
476 are actually copied.
477
478 @see @RefSect{extras.old_value_requirements__templates_,
479 Old Value Requirements}
480 */
481 class old_value { // Copyable (as *).
482 public:
483 // Following implicitly called by ternary operator `... ? ... : null_old()`.
484
485 /**
486 Construct this object from the specified old value when the old value type
487 is copy constructible.
488
489 The specified old value is copied (one time only) using
490 @c boost::contract::old_value_copy, in which case related old value pointer
491 will not be null (no copy is made if postconditions and exception guarantees
492 are not being checked, see @RefMacro{BOOST_CONTRACT_NO_OLDS}).
493
494 @param old Old value to be copied.
495
496 @tparam T Old value type.
497 */
498 template<typename T>
499 /* implicit */ old_value(
500 T const& old,
501 typename boost::enable_if<boost::contract::is_old_value_copyable<T>
502 >::type* = 0
503 )
504 #ifndef BOOST_CONTRACT_NO_OLDS
505 : untyped_copy_(new old_value_copy<T>(old))
506 #endif // Else, leave ptr_ null (thus no copy of T).
507 {}
508
509 /**
510 Construct this object from the specified old value when the old value type
511 is not copyable.
512
513 The specified old value cannot be copied in this case so it is not copied
514 and the related old value pointer will always be null (thus a call to this
515 constructor has no effect and it will likely be optimized away by most
516 compilers).
517
518 @param old Old value (that will not be copied in this case).
519
520 @tparam T Old value type.
521 */
522 template<typename T>
523 /* implicit */ old_value(
524 T const& old,
525 typename boost::disable_if<boost::contract::is_old_value_copyable<T>
526 >::type* = 0
527 ) {} // Leave ptr_ null (thus no copy of T).
528
529 /** @cond */
530 private:
531 explicit old_value() {}
532
533 #ifndef BOOST_CONTRACT_NO_OLDS
534 boost::shared_ptr<void> untyped_copy_; // Type erasure.
535 #endif
536
537 friend class old_pointer;
538 friend BOOST_CONTRACT_DETAIL_DECLSPEC old_value null_old();
539 /** @endcond */
540 };
541
542 /**
543 Convert old value copies to old value pointers.
544
545 This class is often only implicitly used by this library and it does not
546 explicitly appear in user code (that is why this class does not have public
547 constructors, etc.).
548 */
549 class old_pointer { // Copyable (as *).
550 public:
551 /**
552 Convert this object to an actual old value pointer for which the old value
553 type @c T might or not be copyable.
554
555 For example, this is implicitly called when assigning or initializing old
556 value pointers.
557
558 @tparam T Type of the pointed old value.
559 The old value pointer will always be null if this type is not
560 copyable (see
561 @c boost::contract::is_old_value_copyable), but this library
562 will not generate a compile-time error.
563 */
564 template<typename T>
565 /* implicit */ operator old_ptr_if_copyable<T>() {
566 return get<old_ptr_if_copyable<T> >();
567 }
568
569 /**
570 Convert this object to an actual old value pointer for which the old value
571 type @c T must be copyable.
572
573 For example, this is implicitly called when assigning or initializing old
574 value pointers.
575
576 @tparam T Type of the pointed old value. This type must be copyable
577 (see @c boost::contract::is_old_value_copyable),
578 otherwise this library will generate a compile-time error when
579 the old value pointer is dereferenced.
580 */
581 template<typename T>
582 /* implicit */ operator old_ptr<T>() {
583 return get<old_ptr<T> >();
584 }
585
586 /** @cond */
587 private:
588 explicit old_pointer(virtual_* v, old_value const& old)
589 #ifndef BOOST_CONTRACT_NO_OLDS
590 : v_(v), untyped_copy_(old.untyped_copy_)
591 #endif
592 {}
593
594 template<typename Ptr>
595 Ptr get() {
596 #ifndef BOOST_CONTRACT_NO_OLDS
597 if(!boost::contract::is_old_value_copyable<typename
598 Ptr::element_type>::value) {
599 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
600 return Ptr(); // Non-copyable so no old value and return null.
601 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
602 } else if(!v_ && boost::contract::detail::checking::already()) {
603 return Ptr(); // Not checking (so return null).
604 #endif
605 } else if(!v_) {
606 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy_);
607 typedef old_value_copy<typename Ptr::element_type> copied_type;
608 boost::shared_ptr<copied_type> typed_copy = // Un-erase type.
609 boost::static_pointer_cast<copied_type>(untyped_copy_);
610 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy);
611 return Ptr(typed_copy);
612 } else if(
613 v_->action_ == boost::contract::virtual_::push_old_init_copy ||
614 v_->action_ == boost::contract::virtual_::push_old_ftor_copy
615 ) {
616 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy_);
617 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
618 boost::contract::virtual_::push_old_ftor_copy ?
619 v_->old_ftor_copies_
620 :
621 v_->old_init_copies_
622 ;
623 copies.push(untyped_copy_);
624 return Ptr(); // Pushed (so return null).
625 } else if(
626 boost::contract::virtual_::pop_old_init_copy(v_->action_) ||
627 v_->action_ == boost::contract::virtual_::pop_old_ftor_copy
628 ) {
629 // Copy not null, but still pop it from the queue.
630 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
631
632 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
633 boost::contract::virtual_::pop_old_ftor_copy ?
634 v_->old_ftor_copies_
635 :
636 v_->old_init_copies_
637 ;
638 boost::shared_ptr<void> untyped_copy = copies.front();
639 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy);
640 copies.pop();
641
642 typedef old_value_copy<typename Ptr::element_type> copied_type;
643 boost::shared_ptr<copied_type> typed_copy = // Un-erase type.
644 boost::static_pointer_cast<copied_type>(untyped_copy);
645 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy);
646 return Ptr(typed_copy);
647 }
648 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
649 #endif
650 return Ptr();
651 }
652
653 #ifndef BOOST_CONTRACT_NO_OLDS
654 virtual_* v_;
655 boost::shared_ptr<void> untyped_copy_; // Type erasure.
656 #endif
657
658 friend BOOST_CONTRACT_DETAIL_DECLSPEC
659 old_pointer make_old(old_value const&);
660
661 friend BOOST_CONTRACT_DETAIL_DECLSPEC
662 old_pointer make_old(virtual_*, old_value const&);
663 /** @endcond */
664 };
665
666 /**
667 Return a null old value.
668
669 The related old value pointer will also be null.
670 This function is often only used by the code expanded by
671 @RefMacro{BOOST_CONTRACT_OLDOF}.
672
673 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
674
675 @return Null old value.
676 */
677 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
678 old_value null_old();
679
680 /**
681 Make an old value pointer (but not for virtual public functions and public
682 functions overrides).
683
684 The related old value pointer will not be null if the specified old value was
685 actually copied.
686 This function is often only used by code expanded by
687 @c BOOST_CONTRACT_OLDOF(old_expr):
688
689 @code
690 boost::contract::make_old(boost::contract::copy_old() ? old_expr :
691 boost::contract::null_old())
692 @endcode
693
694 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
695
696 @param old Old value which is usually implicitly constructed from the user old
697 value expression to be copied (use the ternary operator <c>?:</c>
698 to avoid evaluating the old value expression all together when
699 @c boost::contract::copy_old() is @c false).
700
701 @return Old value pointer (usually implicitly converted to either
702 @RefClass{boost::contract::old_ptr} or
703 @RefClass{boost::contract::old_ptr_if_copyable} in user code).
704 */
705 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
706 old_pointer make_old(old_value const& old);
707
708 /**
709 Make an old value pointer (for virtual public functions and public functions
710 overrides).
711
712 The related old value pointer will not be null if the specified old value was
713 actually copied.
714 This function is often only used by code expanded by
715 @c BOOST_CONTRACT_OLDOF(v, old_expr):
716
717 @code
718 boost::contract::make_old(v, boost::contract::copy_old(v) ? old_expr :
719 boost::contract::null_old())
720 @endcode
721
722 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
723
724 @param v The trailing parameter of type
725 @RefClass{boost::contract::virtual_}<c>*</c> and default value @c 0
726 from the enclosing virtual or overriding public function declaring
727 the contract.
728 @param old Old value which is usually implicitly constructed from the user old
729 value expression to be copied (use the ternary operator <c>?:</c>
730 to avoid evaluating the old value expression all together when
731 @c boost::contract::copy_old(v) is @c false).
732
733 @return Old value pointer (usually implicitly converted to either
734 @RefClass{boost::contract::old_ptr} or
735 @RefClass{boost::contract::old_ptr_if_copyable} in user code).
736 */
737 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
738 old_pointer make_old(virtual_* v, old_value const& old);
739
740 /**
741 Check if old values need to be copied (but not for virtual public functions and
742 public function overrides).
743
744 For example, this function always returns false when both postconditions and
745 exception guarantees are not being checked (see
746 @RefMacro{BOOST_CONTRACT_NO_OLDS}).
747 This function is often only used by the code expanded by
748 @RefMacro{BOOST_CONTRACT_OLDOF}.
749
750 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
751
752 @return True if old values need to be copied, false otherwise.
753 */
754 inline bool copy_old() {
755 #ifndef BOOST_CONTRACT_NO_OLDS
756 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
757 return !boost::contract::detail::checking::already();
758 #else
759 return true;
760 #endif
761 #else
762 return false; // No post checking, so never copy old values.
763 #endif
764 }
765
766 /**
767 Check if old values need to be copied (for virtual public functions and public
768 function overrides).
769
770 For example, this function always returns false when both postconditions and
771 exception guarantees are not being checked (see
772 @RefMacro{BOOST_CONTRACT_NO_OLDS}).
773 In addition, this function returns false when overridden functions are being
774 called subsequent times by this library to support subcontracting.
775 This function is often only used by the code expanded by
776 @RefMacro{BOOST_CONTRACT_OLDOF}.
777
778 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
779
780 @param v The trailing parameter of type
781 @RefClass{boost::contract::virtual_}<c>*</c> and default value @c 0
782 from the enclosing virtual or overriding public function declaring
783 the contract.
784
785 @return True if old values need to be copied, false otherwise.
786 */
787 inline bool copy_old(virtual_* v) {
788 #ifndef BOOST_CONTRACT_NO_OLDS
789 if(!v) {
790 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
791 return !boost::contract::detail::checking::already();
792 #else
793 return true;
794 #endif
795 }
796 return v->action_ == boost::contract::virtual_::push_old_init_copy ||
797 v->action_ == boost::contract::virtual_::push_old_ftor_copy;
798 #else
799 return false; // No post checking, so never copy old values.
800 #endif
801 }
802
803 } } // namespace
804
805 #ifdef BOOST_CONTRACT_HEADER_ONLY
806 #include <boost/contract/detail/inlined/old.hpp>
807 #endif
808
809 #endif // #include guard
810