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 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.)
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 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.
141 namespace boost { namespace contract {
142 template<> // Specialization.
143 struct is_old_value_copyable<u> : boost::false_type {};
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).
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 @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:
180 class old_value_copy {
182 explicit old_value_copy(T const& old) :
183 old_(value) // 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 old values (if they
208 actually need to be copied).
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 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):
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);
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> 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.
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 constant pointer to a constant object (see
304 @RefSect{contract_programming_overview.constant_correctness,
305 Constant Correctness}).
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>"
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 Check if this old value pointer is null or not.
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 is 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 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).
395 @param other Old value pointer that requires the old value type to be
398 /* implicit */ old_ptr_if_copyable(old_ptr<T> const& other) :
399 typed_copy_(other.typed_copy_) {}
402 Dereference this old value pointer.
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).
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}).
415 T const& operator*() const {
416 BOOST_CONTRACT_DETAIL_DEBUG(typed_copy_);
417 return typed_copy_->old();
421 Structure-dereference this old value pointer.
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).
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}).
434 T const* const operator->() const {
435 if(typed_copy_) return &typed_copy_->old();
439 #ifndef BOOST_CONTRACT_DETAIL_DOXYGEN
440 BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_if_copyable<T>,
444 Check if this old value pointer is null or not (safe-bool operator).
446 (This is implemented using safe-bool emulation on compilers that do not
447 support C++11 explicit type conversion operators.)
449 @return True if this pointer is not null, false otherwise.
451 explicit operator bool() const;
456 #ifndef BOOST_CONTRACT_NO_OLDS
457 explicit old_ptr_if_copyable(boost::shared_ptr<old_value_copy<T> > old)
458 : typed_copy_(old) {}
461 boost::shared_ptr<old_value_copy<T> > typed_copy_;
463 friend class old_pointer;
468 Convert user-specified expressions to old values.
470 This class is often only implicitly used by this library and it does not
471 explicitly appear in user code.
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
478 @see @RefSect{extras.old_value_requirements__templates_,
479 Old Value Requirements}
481 class old_value { // Copyable (as *).
483 // Following implicitly called by ternary operator `... ? ... : null_old()`.
486 Construct this object from the specified old value when the old value type
487 is copy constructible.
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}).
494 @param old Old value to be copied.
496 @tparam T Old value type.
499 /* implicit */ old_value(
501 typename boost::enable_if<boost::contract::is_old_value_copyable<T>
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).
510 Construct this object from the specified old value when the old value type
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
518 @param old Old value (that will not be copied in this case).
520 @tparam T Old value type.
523 /* implicit */ old_value(
525 typename boost::disable_if<boost::contract::is_old_value_copyable<T>
527 ) {} // Leave ptr_ null (thus no copy of T).
531 explicit old_value() {}
533 #ifndef BOOST_CONTRACT_NO_OLDS
534 boost::shared_ptr<void> untyped_copy_; // Type erasure.
537 friend class old_pointer;
538 friend BOOST_CONTRACT_DETAIL_DECLSPEC old_value null_old();
543 Convert old value copies to old value pointers.
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
549 class old_pointer { // Copyable (as *).
552 Convert this object to an actual old value pointer for which the old value
553 type @c T might or not be copyable.
555 For example, this is implicitly called when assigning or initializing old
558 @tparam T Type of the pointed old value.
559 The old value pointer will always be null if this type is not
561 @c boost::contract::is_old_value_copyable), but this library
562 will not generate a compile-time error.
565 /* implicit */ operator old_ptr_if_copyable<T>() {
566 return get<old_ptr_if_copyable<T> >();
570 Convert this object to an actual old value pointer for which the old value
571 type @c T must be copyable.
573 For example, this is implicitly called when assigning or initializing old
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.
582 /* implicit */ operator old_ptr<T>() {
583 return get<old_ptr<T> >();
588 explicit old_pointer(virtual_* v, old_value const& old)
589 #ifndef BOOST_CONTRACT_NO_OLDS
590 : v_(v), untyped_copy_(old.untyped_copy_)
594 template<typename Ptr>
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).
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);
613 v_->action_ == boost::contract::virtual_::push_old_init_copy ||
614 v_->action_ == boost::contract::virtual_::push_old_ftor_copy
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 ?
623 copies.push(untyped_copy_);
624 return Ptr(); // Pushed (so return null).
626 boost::contract::virtual_::pop_old_init_copy(v_->action_) ||
627 v_->action_ == boost::contract::virtual_::pop_old_ftor_copy
629 // Copy not null, but still pop it from the queue.
630 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
632 std::queue<boost::shared_ptr<void> >& copies = v_->action_ ==
633 boost::contract::virtual_::pop_old_ftor_copy ?
638 boost::shared_ptr<void> untyped_copy = copies.front();
639 BOOST_CONTRACT_DETAIL_DEBUG(untyped_copy);
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);
648 BOOST_CONTRACT_DETAIL_DEBUG(!untyped_copy_);
653 #ifndef BOOST_CONTRACT_NO_OLDS
655 boost::shared_ptr<void> untyped_copy_; // Type erasure.
658 friend BOOST_CONTRACT_DETAIL_DECLSPEC
659 old_pointer make_old(old_value const&);
661 friend BOOST_CONTRACT_DETAIL_DECLSPEC
662 old_pointer make_old(virtual_*, old_value const&);
667 Return a null old value.
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}.
673 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
675 @return Null old value.
677 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
678 old_value null_old();
681 Make an old value pointer (but not for virtual public functions and public
682 functions overrides).
684 The related old value pointer will not be null if the specified old value was
686 This function is often only used by code expanded by
687 @c BOOST_CONTRACT_OLDOF(old_expr):
690 boost::contract::make_old(boost::contract::copy_old() ? old_expr :
691 boost::contract::null_old())
694 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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).
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).
705 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
706 old_pointer make_old(old_value const& old);
709 Make an old value pointer (for virtual public functions and public functions
712 The related old value pointer will not be null if the specified old value was
714 This function is often only used by code expanded by
715 @c BOOST_CONTRACT_OLDOF(v, old_expr):
718 boost::contract::make_old(v, boost::contract::copy_old(v) ? old_expr :
719 boost::contract::null_old())
722 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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
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).
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).
737 /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */
738 old_pointer make_old(virtual_* v, old_value const& old);
741 Check if old values need to be copied (but not for virtual public functions and
742 public function overrides).
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}.
750 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
752 @return True if old values need to be copied, false otherwise.
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();
762 return false; // No post checking, so never copy old values.
767 Check if old values need to be copied (for virtual public functions and public
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}.
778 @see @RefSect{extras.no_macros__and_no_variadic_macros_, No Macros}
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
785 @return True if old values need to be copied, false otherwise.
787 inline bool copy_old(virtual_* v) {
788 #ifndef BOOST_CONTRACT_NO_OLDS
790 #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
791 return !boost::contract::detail::checking::already();
796 return v->action_ == boost::contract::virtual_::push_old_init_copy ||
797 v->action_ == boost::contract::virtual_::push_old_ftor_copy;
799 return false; // No post checking, so never copy old values.
805 #ifdef BOOST_CONTRACT_HEADER_ONLY
806 #include <boost/contract/detail/inlined/old.hpp>
809 #endif // #include guard