destructor.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #ifndef BOOST_CONTRACT_DESTRUCTOR_HPP_
  2. #define BOOST_CONTRACT_DESTRUCTOR_HPP_
  3. // Copyright (C) 2008-2018 Lorenzo Caminiti
  4. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  5. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  6. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  7. /** @file
  8. Program contracts for destructors.
  9. */
  10. #include <boost/contract/core/config.hpp>
  11. #include <boost/contract/core/specify.hpp>
  12. #include <boost/contract/core/access.hpp>
  13. #if !defined(BOOST_CONTRACT_NO_DESTRUCTORS) || \
  14. !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
  15. defined(BOOST_CONTRACT_STATIC_LINK)
  16. #include <boost/contract/detail/operation/destructor.hpp>
  17. #endif
  18. namespace boost { namespace contract {
  19. /**
  20. Program contracts for destructors.
  21. This is used to specify postconditions, exception guarantees, old value copies
  22. at body, and check class invariants for destructors (destructors cannot have
  23. preconditions, see
  24. @RefSect{contract_programming_overview.destructor_calls, Destructor Calls}):
  25. @code
  26. class u {
  27. friend class boost::contract::access;
  28. void invariant() const { // Optional (as for static and volatile).
  29. BOOST_CONTRACT_ASSERT(...);
  30. ...
  31. }
  32. public:
  33. ~u() {
  34. boost::contract::old_ptr<old_type> old_var;
  35. boost::contract::check c = boost::contract::destructor(this)
  36. // No `.precondition` (destructors have no preconditions).
  37. .old([&] { // Optional.
  38. old_var = BOOST_CONTRACT_OLDOF(old_expr);
  39. ...
  40. })
  41. .postcondition([&] { // Optional.
  42. BOOST_CONTRACT_ASSERT(...);
  43. ...
  44. })
  45. .except([&] { // Optional.
  46. BOOST_CONTRACT_ASSERT(...);
  47. ...
  48. })
  49. ;
  50. ... // Destructor body.
  51. }
  52. ...
  53. };
  54. @endcode
  55. For optimization, this can be omitted for destructors that do not have
  56. postconditions and exception guarantees, within classes that have no invariants.
  57. @see @RefSect{tutorial.destructors, Destructors}
  58. @param obj The object @c this from the scope of the enclosing destructor
  59. declaring the contract.
  60. (Destructors check all class invariants, including static and
  61. volatile invariants, see @RefSect{tutorial.class_invariants,
  62. Class Invariants} and
  63. @RefSect{extras.volatile_public_functions,
  64. Volatile Public Functions}).
  65. @tparam Class The type of the class containing the destructor declaring the
  66. contract.
  67. (Usually this template parameter is automatically deduced by C++
  68. and it does not need to be explicitly specified by programmers.)
  69. @return The result of this function must be assigned to a variable of type
  70. @RefClass{boost::contract::check} declared explicitly (i.e., without
  71. using C++11 @c auto declarations) and locally just before the code of
  72. the destructor body (otherwise this library will generate a run-time
  73. error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}).
  74. */
  75. template<class Class>
  76. specify_old_postcondition_except<> destructor(Class* obj) {
  77. // Must #if also on ..._PRECONDITIONS here because specify_... is generic.
  78. #if !defined(BOOST_CONTRACT_NO_DESTRUCTORS) || \
  79. !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
  80. defined(BOOST_CONTRACT_STATIC_LINK)
  81. return specify_old_postcondition_except<>(
  82. new boost::contract::detail::destructor<Class>(obj));
  83. #else
  84. return specify_old_postcondition_except<>();
  85. #endif
  86. }
  87. } } // namespace
  88. #endif // #include guard