access.hpp 6.3 KB

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