destructor.hpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #ifndef BOOST_CONTRACT_DETAIL_DESTRUCTOR_HPP_
  2. #define BOOST_CONTRACT_DETAIL_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. #include <boost/contract/core/exception.hpp>
  8. #include <boost/contract/core/config.hpp>
  9. #include <boost/contract/detail/condition/cond_inv.hpp>
  10. #include <boost/contract/detail/none.hpp>
  11. #if !defined(BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION) && ( \
  12. !defined(BOOST_CONTRACT_NO_INVARIANTS) || \
  13. !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
  14. !defined(BOOST_CONTRACT_NO_EXCEPTS))
  15. #include <boost/contract/detail/checking.hpp>
  16. #endif
  17. #if !defined(BOOST_CONTRACT_NO_EXIT_INVARIANTS) || \
  18. !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
  19. !defined(BOOST_CONTRACT_NO_EXCEPTS)
  20. #include <boost/config.hpp>
  21. #include <exception>
  22. #endif
  23. namespace boost { namespace contract { namespace detail {
  24. // Dtor subcontracting impl via C++ obj destruction mechanism.
  25. template<class C> // Non-copyable base.
  26. class destructor : public cond_inv</* VR = */ none, C> {
  27. public:
  28. explicit destructor(C* obj) : cond_inv</* VR = */ none, C>(
  29. boost::contract::from_destructor, obj) {}
  30. private:
  31. #if !defined(BOOST_CONTRACT_NO_ENTRY_INVARIANTS) || \
  32. !defined(BOOST_CONTRACT_NO_OLDS)
  33. void init() /* override */ {
  34. #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
  35. if(checking::already()) return;
  36. #endif
  37. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  38. {
  39. #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
  40. checking k;
  41. #endif
  42. // Obj exists (before dtor body), check static and non- inv.
  43. this->check_entry_all_inv();
  44. // Dtor cannot have pre because it has no parameters.
  45. }
  46. #endif
  47. #ifndef BOOST_CONTRACT_NO_OLDS
  48. this->copy_old();
  49. #endif
  50. }
  51. #endif
  52. public:
  53. #if !defined(BOOST_CONTRACT_NO_EXIT_INVARIANTS) || \
  54. !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
  55. !defined(BOOST_CONTRACT_NO_EXCEPTS)
  56. ~destructor() BOOST_NOEXCEPT_IF(false) {
  57. this->assert_initialized();
  58. #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
  59. if(checking::already()) return;
  60. checking k;
  61. #endif
  62. // If dtor body threw, obj still exists so check subcontracted
  63. // static and non- inv (but no post because of throw). Otherwise,
  64. // obj destructed so check static inv and post (even if there is no
  65. // obj after dtor body, this library allows dtor post, for example
  66. // to check static members for an instance counter class).
  67. // NOTE: In theory C++ destructors should not throw, but the
  68. // language allows for that (even if in C++11 dtors declarations are
  69. // implicitly noexcept(true) unless specified otherwise) so this
  70. // library must handle such a case.
  71. if(std::uncaught_exception()) {
  72. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  73. this->check_exit_all_inv();
  74. #endif
  75. #ifndef BOOST_CONTRACT_NO_EXCEPTS
  76. this->check_except();
  77. #endif
  78. } else {
  79. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  80. this->check_exit_static_inv();
  81. #endif
  82. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  83. this->check_post(none());
  84. #endif
  85. }
  86. }
  87. #endif
  88. };
  89. } } } // namespace
  90. #endif // #include guard