1 2 // Copyright (C) 2008-2018 Lorenzo Caminiti 3 // Distributed under the Boost Software License, Version 1.0 (see accompanying 4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). 5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html 6 7 // Test overrides with mixed access level from (single) base. 8 9 #include "../detail/oteststream.hpp" 10 #include <boost/contract/public_function.hpp> 11 #include <boost/contract/function.hpp> 12 #include <boost/contract/base_types.hpp> 13 #include <boost/contract/override.hpp> 14 #include <boost/contract/check.hpp> 15 #include <boost/detail/lightweight_test.hpp> 16 #include <sstream> 17 18 boost::contract::test::detail::oteststream out; 19 20 struct b { // Test all access levels (public, protected, and private). call(b & me)21 friend void call(b& me) { // Test polymorphic calls (object by &). 22 me.f(); 23 me.g(); 24 me.h(); 25 } 26 statci_invb27 static void statci_inv() { out << "b::static_inv" << std::endl; } invariantb28 void invariant() const { out << "b::inv" << std::endl; } 29 fb30 virtual void f(boost::contract::virtual_* v = 0) { 31 boost::contract::check c = boost::contract::public_function(v, this) 32 .precondition([] { out << "b::f::pre" << std::endl; }) 33 .old([] { out << "b::f::old" << std::endl; }) 34 .postcondition([] { out << "b::f::post" << std::endl; }) 35 ; 36 out << "b::f::body" << std::endl; 37 } 38 39 // NOTE: Both protected and private virtual members must declare 40 // extra `virtual_* = 0` parameter (otherwise they cannot be overridden in 41 // derived classes with contracts because C++ uses also default parameters 42 // to match signature of overriding functions). 43 44 protected: gb45 virtual void g(boost::contract::virtual_* /* v */= 0) { 46 boost::contract::check c = boost::contract::function() 47 .precondition([] { out << "b::g::pre" << std::endl; }) 48 .old([] { out << "b::g::old" << std::endl; }) 49 .postcondition([] { out << "b::g::post" << std::endl; }) 50 ; 51 out << "b::g::body" << std::endl; 52 } 53 54 private: hb55 virtual void h(boost::contract::virtual_* /* v */ = 0) { 56 boost::contract::check c = boost::contract::function() 57 .precondition([] { out << "b::h::pre" << std::endl; }) 58 .old([] { out << "b::h::old" << std::endl; }) 59 .postcondition([] { out << "b::h::post" << std::endl; }) 60 ; 61 out << "b::h::body" << std::endl; 62 } 63 }; 64 65 struct a // Test overrides with mixed access levels from base. 66 #define BASES public b 67 : BASES 68 { 69 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 70 #undef BASES 71 statci_inva72 static void statci_inv() { out << "a::static_inv" << std::endl; } invarianta73 void invariant() const { out << "a::inv" << std::endl; } 74 fa75 virtual void f(boost::contract::virtual_* v = 0) /* override */ { 76 boost::contract::check c = boost::contract::public_function<override_f>( 77 v, &a::f, this) 78 .precondition([] { out << "a::f::pre" << std::endl; }) 79 .old([] { out << "a::f::old" << std::endl; }) 80 .postcondition([] { out << "a::f::post" << std::endl; }) 81 ; 82 out << "a::f::body" << std::endl; 83 } BOOST_CONTRACT_OVERRIDESa84 BOOST_CONTRACT_OVERRIDES(f) 85 86 // Following do not override public members so no `override_...` param and 87 // they do not actually subcontract. 88 89 virtual void g(boost::contract::virtual_* v = 0) /* override */ { 90 boost::contract::check c = boost::contract::public_function(v, this) 91 .precondition([] { out << "a::g::pre" << std::endl; }) 92 .old([] { out << "a::g::old" << std::endl; }) 93 .postcondition([] { out << "a::g::post" << std::endl; }) 94 ; 95 out << "a::g::body" << std::endl; 96 } 97 ha98 virtual void h(boost::contract::virtual_* v = 0) /* override */ { 99 boost::contract::check c = boost::contract::public_function(v, this) 100 .precondition([] { out << "a::h::pre" << std::endl; }) 101 .old([] { out << "a::h::old" << std::endl; }) 102 .postcondition([] { out << "a::h::post" << std::endl; }) 103 ; 104 out << "a::h::body" << std::endl; 105 } 106 }; 107 main()108int main() { 109 std::ostringstream ok; 110 111 b bb; 112 out.str(""); 113 call(bb); 114 ok.str(""); ok 115 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 116 << "b::inv" << std::endl 117 #endif 118 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 119 << "b::f::pre" << std::endl 120 #endif 121 #ifndef BOOST_CONTRACT_NO_OLDS 122 << "b::f::old" << std::endl 123 #endif 124 << "b::f::body" << std::endl 125 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 126 << "b::inv" << std::endl 127 #endif 128 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 129 << "b::f::post" << std::endl 130 #endif 131 132 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 133 << "b::g::pre" << std::endl 134 #endif 135 #ifndef BOOST_CONTRACT_NO_OLDS 136 << "b::g::old" << std::endl 137 #endif 138 << "b::g::body" << std::endl 139 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 140 << "b::g::post" << std::endl 141 #endif 142 143 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 144 << "b::h::pre" << std::endl 145 #endif 146 #ifndef BOOST_CONTRACT_NO_OLDS 147 << "b::h::old" << std::endl 148 #endif 149 << "b::h::body" << std::endl 150 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 151 << "b::h::post" << std::endl 152 #endif 153 ; 154 BOOST_TEST(out.eq(ok.str())); 155 156 a aa; 157 out.str(""); 158 call(aa); 159 ok.str(""); ok 160 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 161 << "b::inv" << std::endl 162 << "a::inv" << std::endl 163 #endif 164 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 165 << "b::f::pre" << std::endl 166 #endif 167 #ifndef BOOST_CONTRACT_NO_OLDS 168 << "b::f::old" << std::endl 169 << "a::f::old" << std::endl 170 #endif 171 << "a::f::body" << std::endl 172 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 173 << "b::inv" << std::endl 174 << "a::inv" << std::endl 175 #endif 176 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 177 << "b::f::old" << std::endl 178 << "b::f::post" << std::endl 179 << "a::f::post" << std::endl 180 #endif 181 182 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 183 << "a::inv" << std::endl 184 #endif 185 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 186 << "a::g::pre" << std::endl 187 #endif 188 #ifndef BOOST_CONTRACT_NO_OLDS 189 << "a::g::old" << std::endl 190 #endif 191 << "a::g::body" << std::endl 192 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 193 << "a::inv" << std::endl 194 #endif 195 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 196 << "a::g::post" << std::endl 197 #endif 198 199 #ifndef BOOST_CONTRACT_NO_ENTRY_INVARIANTS 200 << "a::inv" << std::endl 201 #endif 202 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 203 << "a::h::pre" << std::endl 204 #endif 205 #ifndef BOOST_CONTRACT_NO_OLDS 206 << "a::h::old" << std::endl 207 #endif 208 << "a::h::body" << std::endl 209 #ifndef BOOST_CONTRACT_NO_EXIT_INVARIANTS 210 << "a::inv" << std::endl 211 #endif 212 #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS 213 << "a::h::post" << std::endl 214 #endif 215 ; 216 BOOST_TEST(out.eq(ok.str())); 217 218 return boost::report_errors(); 219 } 220 221