virtual.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #ifndef BOOST_CONTRACT_VIRTUAL_HPP_
  2. #define BOOST_CONTRACT_VIRTUAL_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. Handle virtual public functions with contracts (for subcontracting).
  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_CONDITIONS
  13. #include <boost/contract/detail/decl.hpp>
  14. #endif
  15. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  16. #include <boost/any.hpp>
  17. #endif
  18. #ifndef BOOST_CONTRACT_NO_OLDS
  19. #include <boost/shared_ptr.hpp>
  20. #include <queue>
  21. #endif
  22. namespace boost { namespace contract {
  23. #ifndef BOOST_CONTRACT_NO_CONDITIONS
  24. namespace detail {
  25. BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
  26. /* is_friend = */ 0, OO, RR, FF, CC, AArgs);
  27. }
  28. #endif
  29. /**
  30. Type of extra function parameter to handle contracts for virtual public
  31. functions (for subcontracting).
  32. Virtual public functions (and therefore also public function overrides)
  33. declaring contracts using this library must specify an extra function parameter
  34. at the very end of their parameter list.
  35. This parameter must be a pointer to this class and it must have default value
  36. @c 0 or @c nullptr (this extra parameter is often named @c v in this
  37. documentation, but any name can be used):
  38. @code
  39. class u {
  40. public:
  41. virtual void f(int x, boost::contract::virtual_* v = 0) { // Declare `v`.
  42. ... // Contract declaration (which will use `v`) and function body.
  43. }
  44. ...
  45. };
  46. @endcode
  47. In practice this extra parameter does not alter the calling interface of the
  48. enclosing function declaring the contract because it is always the very last
  49. parameter and it has a default value (so it can always be omitted when users
  50. call the function).
  51. This extra parameter must be passed to
  52. @RefFunc{boost::contract::public_function}, @RefMacro{BOOST_CONTRACT_OLDOF}, and
  53. all other operations of this library that accept a pointer to
  54. @RefClass{boost::contract::virtual_}.
  55. A part from that, this class is not intended to be directly used by programmers
  56. (and that is why this class does not have any public member and it is not
  57. copyable).
  58. @see @RefSect{tutorial.virtual_public_functions, Virtual Public Functions},
  59. @RefSect{tutorial.public_function_overrides__subcontracting_,
  60. Public Function Overrides}
  61. */
  62. class virtual_ { // Non-copyable (see below) to avoid copy queue, stack, etc.
  63. /** @cond */
  64. private: // No public API (so users cannot use it directly by mistake).
  65. // No boost::noncopyable to avoid its overhead when contracts disabled.
  66. virtual_(virtual_&);
  67. virtual_& operator=(virtual_&);
  68. #ifndef BOOST_CONTRACT_NO_CONDITIONS
  69. enum action_enum {
  70. // virtual_ always held/passed as ptr so nullptr used for user call.
  71. no_action,
  72. #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS
  73. check_entry_inv,
  74. #endif
  75. #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
  76. check_pre,
  77. #endif
  78. #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS
  79. check_exit_inv,
  80. #endif
  81. #ifndef BOOST_CONTRACT_NO_OLDS
  82. // For outside .old(...).
  83. push_old_init_copy,
  84. // pop_old_init_copy as static function below.
  85. // For inside .old(...).
  86. call_old_ftor,
  87. push_old_ftor_copy,
  88. pop_old_ftor_copy,
  89. #endif
  90. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  91. check_post,
  92. #endif
  93. #ifndef BOOST_CONTRACT_NO_EXCEPTS
  94. check_except,
  95. #endif
  96. };
  97. #endif
  98. #ifndef BOOST_CONTRACT_NO_OLDS
  99. // Not just an enum value because the logical combination of two values.
  100. inline static bool pop_old_init_copy(action_enum a) {
  101. return
  102. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  103. a == check_post
  104. #endif
  105. #if !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) && \
  106. !defined(BOOST_CONTRACT_NO_EXCEPTS)
  107. ||
  108. #endif
  109. #ifndef BOOST_CONTRACT_NO_EXCEPTS
  110. a == check_except
  111. #endif
  112. ;
  113. }
  114. #endif
  115. #ifndef BOOST_CONTRACT_NO_CONDITIONS
  116. explicit virtual_(action_enum a) :
  117. action_(a)
  118. , failed_(false)
  119. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  120. , result_type_name_()
  121. , result_optional_()
  122. #endif
  123. {}
  124. #endif
  125. #ifndef BOOST_CONTRACT_NO_CONDITIONS
  126. action_enum action_;
  127. bool failed_;
  128. #endif
  129. #ifndef BOOST_CONTRACT_NO_OLDS
  130. std::queue<boost::shared_ptr<void> > old_init_copies_;
  131. std::queue<boost::shared_ptr<void> > old_ftor_copies_;
  132. #endif
  133. #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
  134. boost::any result_ptr_; // Result for virtual and overriding functions.
  135. char const* result_type_name_;
  136. bool result_optional_;
  137. #endif
  138. // Friends (used to limit library's public API).
  139. #ifndef BOOST_CONTRACT_NO_OLDS
  140. friend bool copy_old(virtual_*);
  141. friend class old_pointer;
  142. #endif
  143. #ifndef BOOST_CONTRACT_NO_CONDITIONS
  144. BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
  145. /* is_friend = */ 1, OO, RR, FF, CC, AArgs);
  146. #endif
  147. /** @endcond */
  148. };
  149. } } // namespace
  150. #endif // #include guard