constructor_precondition.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. #ifndef BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_HPP_
  2. #define BOOST_CONTRACT_CONSTRUCTOR_PRECONDITION_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 preconditions for constructors.
  9. */
  10. // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes.
  11. #include <boost/contract/core/config.hpp>
  12. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  13. #include <boost/contract/core/exception.hpp>
  14. #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
  15. #include <boost/contract/detail/checking.hpp>
  16. #endif
  17. #endif
  18. namespace boost { namespace contract {
  19. /**
  20. Program preconditions for constructors.
  21. This class must be the very first base of the class declaring the
  22. constructor for which preconditions are programmed (that way constructor
  23. arguments can be checked by preconditions even before they are used to
  24. initialize other base classes):
  25. @code
  26. class u
  27. #define BASES private boost::contract::constructor_precondition<u>, \
  28. public b
  29. : BASES
  30. {
  31. friend class boost::contract::access;
  32. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  33. #undef BASES
  34. public:
  35. explicit u(unsigned x) :
  36. boost::contract::constructor_precondition<u>([&] {
  37. BOOST_CONTRACT_ASSERT(x != 0);
  38. ...
  39. }),
  40. b(1.0 / float(x))
  41. {
  42. ...
  43. }
  44. ...
  45. };
  46. @endcode
  47. User-defined classes should inherit privately from this class (to not alter the
  48. public interface of user-defined classes).
  49. In addition, this class should never be declared as a virtual base (because
  50. virtual bases are initialized only once across the entire inheritance hierarchy
  51. preventing preconditions of other base classes from being checked).
  52. This class cannot be used this way in a @c union because unions cannot have base
  53. classes in C++.
  54. Instead, this class is used in a @c union to declare a local object within the
  55. constructor definition just before @RefFunc{boost::contract::constructor} is
  56. used (see @RefSect{extras.unions, Unions}).
  57. @see @RefSect{tutorial.constructors, Constructors}
  58. @tparam Class The class type of the constructor for which preconditions are
  59. being programmed.
  60. */
  61. template<class Class>
  62. class constructor_precondition { // Copyable (has no data).
  63. public:
  64. /**
  65. Construct this object without specifying constructor preconditions.
  66. This is implicitly called for those constructors of the contracted class
  67. that do not specify preconditions.
  68. @note The implementation of this library is optimized so that calling this
  69. default constructor should amount to negligible compile-time and
  70. run-time overheads (likely to be optimized away completely by most
  71. compilers).
  72. */
  73. constructor_precondition() {}
  74. /**
  75. Construct this object specifying constructor preconditions.
  76. @param f Nullary functor called by this library to check constructor
  77. preconditions @c f().
  78. Assertions within this functor call are usually programmed
  79. using @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown
  80. by a call to this functor indicates a contract failure (and will
  81. result in this library calling
  82. @RefFunc{boost::contract::precondition_failure}).
  83. This functor should capture variables by (constant) value, or
  84. better by (constant) reference to avoid extra copies.
  85. */
  86. template<typename F>
  87. explicit constructor_precondition(F const& f) {
  88. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  89. try {
  90. #ifndef BOOST_CONTRACT_ALL_DISABLE_NO_ASSERTION
  91. if(boost::contract::detail::checking::already()) return;
  92. #ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
  93. boost::contract::detail::checking k;
  94. #endif
  95. #endif
  96. f();
  97. } catch(...) { precondition_failure(from_constructor); }
  98. #endif
  99. }
  100. // Default copy operations (so user's derived classes can be copied, etc.).
  101. };
  102. } } // namespace
  103. #endif // #include guard