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