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