access.hpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #ifndef BOOST_CONTRACT_ACCESS_HPP_
  2. #define BOOST_CONTRACT_ACCESS_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. Allow to declare invariants, base types, etc all as private members.
  9. */
  10. // IMPORTANT: Included by contract_macro.hpp so must #if-guard all its includes.
  11. #include <boost/contract/core/config.hpp>
  12. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  13. defined(BOOST_CONTRACT_STATIC_LINK)
  14. #include <boost/contract/detail/decl.hpp>
  15. #include <boost/contract/detail/type_traits/mirror.hpp>
  16. #endif
  17. #ifndef BOOST_CONTRACT_NO_INVARIANTS
  18. #include <boost/contract/detail/debug.hpp>
  19. #include <boost/function_types/property_tags.hpp>
  20. #include <boost/mpl/vector.hpp>
  21. #endif
  22. namespace boost { namespace contract {
  23. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  24. defined(BOOST_CONTRACT_STATIC_LINK)
  25. class virtual_;
  26. namespace detail {
  27. BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
  28. /* is_friend = */ 0, OO, RR, FF, CC, AArgs);
  29. }
  30. #endif
  31. #ifndef BOOST_CONTRACT_NO_INVARIANTS
  32. namespace detail {
  33. template<typename RR, class CC>
  34. class cond_inv;
  35. }
  36. #endif
  37. /**
  38. Declare this class as friend to program invariants and base types as private
  39. members.
  40. Declare this class a friend of the user-defined class specifying the contracts
  41. and then invariant functions and the base types @c typedef can be declared as
  42. non-public members:
  43. @code
  44. class u
  45. #define BASES public b, private w
  46. : BASES
  47. {
  48. friend class boost::contract::access;
  49. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Private.
  50. #undef BASES
  51. void invariant() const { ... } // Private (same for static and volatile).
  52. public:
  53. ...
  54. };
  55. @endcode
  56. In real code, programmers will likely chose to declare this class as friend so
  57. to fully control public interfaces of their user-defined classes (this is not
  58. extensively done in the examples of this documentation only for brevity).
  59. This class is not intended to be directly used by programmers a part from
  60. being declared as @c friend (and that is why this class does not have any public
  61. member and it is not copyable).
  62. @warning Not declaring this class friend of user-defined classes will cause
  63. compiler errors on some compilers (e.g., MSVC) because the private
  64. members needed to check the contracts will not be accessible.
  65. On other compilers (e.g., GCC and CLang), the private access will
  66. instead fail SFINAE and no compiler error will be reported while
  67. invariants and subcontracting will be silently skipped at run-time.
  68. Therefore, programmers must make sure to either declare this class
  69. as friend or to always declare invariant functions and base types
  70. @c typedef as public members.
  71. @see @RefSect{advanced.access_specifiers, Access Specifiers}
  72. */
  73. class access { // Non-copyable (see below).
  74. /** @cond */
  75. private: // No public APIs (so users cannot use it directly by mistake).
  76. access(); // Should never be constructed (not even internally).
  77. ~access();
  78. // No boost::noncopyable to avoid its overhead when contracts disabled.
  79. access(access&);
  80. access& operator=(access&);
  81. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  82. defined(BOOST_CONTRACT_STATIC_LINK)
  83. BOOST_CONTRACT_DETAIL_MIRROR_HAS_TYPE(has_base_types,
  84. BOOST_CONTRACT_BASES_TYPEDEF)
  85. template<class C>
  86. struct base_types_of {
  87. typedef typename C::BOOST_CONTRACT_BASES_TYPEDEF type;
  88. };
  89. #endif
  90. #ifndef BOOST_CONTRACT_NO_INVARIANTS
  91. BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION(
  92. has_static_invariant_f, BOOST_CONTRACT_STATIC_INVARIANT_FUNC)
  93. BOOST_CONTRACT_DETAIL_MIRROR_HAS_STATIC_MEMBER_FUNCTION(
  94. has_static_invariant_s, BOOST_CONTRACT_STATIC_INVARIANT_FUNC)
  95. template<class C>
  96. struct has_static_invariant : has_static_invariant_s<C, void,
  97. boost::mpl::vector<> > {};
  98. template<class C>
  99. static void static_invariant() {
  100. C::BOOST_CONTRACT_STATIC_INVARIANT_FUNC();
  101. }
  102. template<class C>
  103. class static_invariant_addr { // Class so to pass it as tparam.
  104. typedef void (*func_ptr)();
  105. public:
  106. static func_ptr apply() {
  107. return &C::BOOST_CONTRACT_STATIC_INVARIANT_FUNC;
  108. }
  109. };
  110. BOOST_CONTRACT_DETAIL_MIRROR_HAS_MEMBER_FUNCTION(
  111. has_invariant_f, BOOST_CONTRACT_INVARIANT_FUNC)
  112. BOOST_CONTRACT_DETAIL_MIRROR_HAS_STATIC_MEMBER_FUNCTION(
  113. has_invariant_s, BOOST_CONTRACT_INVARIANT_FUNC)
  114. template<class C>
  115. struct has_cv_invariant : has_invariant_f<C, void, boost::mpl::vector<>,
  116. boost::function_types::cv_qualified> {};
  117. template<class C>
  118. struct has_const_invariant : has_invariant_f<C, void, boost::mpl::
  119. vector<>, boost::function_types::const_qualified> {};
  120. template<class C>
  121. static void cv_invariant(C const volatile* obj) {
  122. BOOST_CONTRACT_DETAIL_DEBUG(obj);
  123. obj->BOOST_CONTRACT_INVARIANT_FUNC();
  124. }
  125. template<class C>
  126. static void const_invariant(C const* obj) {
  127. BOOST_CONTRACT_DETAIL_DEBUG(obj);
  128. obj->BOOST_CONTRACT_INVARIANT_FUNC();
  129. }
  130. #endif
  131. // Friends (used to limit library's public API).
  132. // NOTE: Using friends here and in all other places in this library
  133. // does not increase compilation times (I experimented replacing all
  134. // friends with public and got the same compilation times).
  135. #if !defined(BOOST_CONTRACT_NO_CONDITIONS) || \
  136. defined(BOOST_CONTRACT_STATIC_LINK)
  137. BOOST_CONTRACT_DETAIL_DECL_DETAIL_COND_SUBCONTRACTING_Z(1,
  138. /* is_friend = */ 1, OO, RR, FF, CC, AArgs);
  139. BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
  140. OO, RR, FF, CC, AArgs, vv, rr, ff, oobj, aargs)
  141. #endif
  142. #ifndef BOOST_CONTRACT_NO_INVARIANTS
  143. template<typename RR, class CC>
  144. friend class boost::contract::detail::cond_inv;
  145. #endif
  146. /** @endcond */
  147. };
  148. } } // namespace
  149. #endif // #include guard