|
|
|||
File indexing completed on 2025-12-16 09:45:03
0001 0002 #ifndef BOOST_CONTRACT_PUBLIC_FUNCTION_HPP_ 0003 #define BOOST_CONTRACT_PUBLIC_FUNCTION_HPP_ 0004 0005 // Copyright (C) 2008-2018 Lorenzo Caminiti 0006 // Distributed under the Boost Software License, Version 1.0 (see accompanying 0007 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). 0008 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html 0009 0010 /** @file 0011 Program contracts for public functions (including subcontracting). 0012 The different overloads handle public functions that are static, virtual void, 0013 virtual non-void, overriding void, and overriding non-void. 0014 */ 0015 0016 #include <boost/contract/core/config.hpp> 0017 #include <boost/contract/core/specify.hpp> 0018 #include <boost/contract/core/access.hpp> 0019 #include <boost/contract/core/virtual.hpp> 0020 /** @cond */ 0021 // Needed within macro expansions below instead of defined(...) (PRIVATE macro). 0022 #if !defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS) || \ 0023 defined(BOOST_CONTRACT_STATIC_LINK) 0024 #define BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 1 0025 #else 0026 #define BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 0 0027 #endif 0028 /** @endcond */ 0029 #include <boost/contract/detail/decl.hpp> 0030 #include <boost/contract/detail/tvariadic.hpp> 0031 #if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 0032 #include <boost/contract/detail/operation/static_public_function.hpp> 0033 #include <boost/contract/detail/operation/public_function.hpp> 0034 #include <boost/contract/detail/type_traits/optional.hpp> 0035 #include <boost/contract/detail/none.hpp> 0036 #include <boost/function_types/result_type.hpp> 0037 #include <boost/function_types/function_arity.hpp> 0038 #include <boost/optional.hpp> 0039 #include <boost/type_traits/remove_reference.hpp> 0040 #include <boost/type_traits/is_same.hpp> 0041 #include <boost/static_assert.hpp> 0042 #include <boost/preprocessor/tuple/eat.hpp> 0043 #endif 0044 #if !BOOST_CONTRACT_DETAIL_TVARIADIC 0045 #include <boost/preprocessor/repetition/repeat.hpp> 0046 #include <boost/preprocessor/arithmetic/sub.hpp> 0047 #include <boost/preprocessor/arithmetic/inc.hpp> 0048 #endif 0049 #include <boost/preprocessor/control/expr_iif.hpp> 0050 #include <boost/preprocessor/control/iif.hpp> 0051 #include <boost/preprocessor/facilities/empty.hpp> 0052 #include <boost/preprocessor/punctuation/comma_if.hpp> 0053 0054 namespace boost { namespace contract { 0055 0056 // NOTE: Override and (optionally) VirtualResult allowed only when v is present 0057 // because: 0058 // * An overriding func must override a base func declared virtual so with 0059 // v extra param, thus the overriding func must also always have v (i.e., 0060 // Override might be present only if v is also present). However, the first 0061 // appearing virtual func (e.g., in root class) will not override any 0062 // previously declared virtual func so does not need Override (i.e., Override 0063 // always optional). 0064 // Furthermore, F needs to be specified only together with Override. 0065 // * VirtualResult is only used for virtual functions (i.e., VirtualResult might 0066 // be present only if v is also present). 0067 // However, VirtualResult is never specified, not even for virtual functions, 0068 // when the return type is void (i.e., VirtualResult always optional). 0069 0070 /** 0071 Program contracts for static public functions. 0072 0073 This is used to specify preconditions, postconditions, exception guarantees, old 0074 value copies at body, and check static class invariants for static public 0075 functions: 0076 0077 @code 0078 class u { 0079 friend class boost::contract::access; 0080 0081 static void static_invariant() { // Optional (as for non-static). 0082 BOOST_CONTRACT_ASSERT(...); 0083 ... 0084 } 0085 0086 public: 0087 static void f(...) { 0088 boost::contract::old_ptr<old_type> old_var; 0089 boost::contract::check c = boost::contract::public_function<u>() 0090 .precondition([&] { // Optional. 0091 BOOST_CONTRACT_ASSERT(...); 0092 ... 0093 }) 0094 .old([&] { // Optional. 0095 old_var = BOOST_CONTRACT_OLDOF(old_expr); 0096 ... 0097 }) 0098 .postcondition([&] { // Optional. 0099 BOOST_CONTRACT_ASSERT(...); 0100 ... 0101 }) 0102 .except([&] { // Optional. 0103 BOOST_CONTRACT_ASSERT(...); 0104 ... 0105 }) 0106 ; 0107 0108 ... // Function body. 0109 } 0110 0111 ... 0112 }; 0113 @endcode 0114 0115 For optimization, this can be omitted for static public functions that do not 0116 have preconditions, postconditions and exception guarantees, within classes that 0117 have no static invariants. 0118 0119 @see @RefSect{tutorial.static_public_functions, Static Public Functions} 0120 0121 @tparam Class The type of the class containing the static public function 0122 declaring the contract. 0123 This template parameter must be explicitly specified for static 0124 public functions (because they have no object @c this so there 0125 is no function argument from which this type template parameter 0126 can be automatically deduced by C++). 0127 0128 @return The result of this function must be assigned to a variable of type 0129 @RefClass{boost::contract::check} declared explicitly (i.e., without 0130 using C++11 @c auto declarations) and locally just before the code of 0131 the static public function body (otherwise this library will generate a 0132 run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0133 */ 0134 template<class Class> 0135 specify_precondition_old_postcondition_except<> public_function() { 0136 #if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 0137 return specify_precondition_old_postcondition_except<>( 0138 new boost::contract::detail::static_public_function<Class>()); 0139 #else 0140 return specify_precondition_old_postcondition_except<>(); 0141 #endif 0142 } 0143 0144 /** 0145 Program contracts for public functions that are not static, not virtual, and do 0146 not not override. 0147 0148 This is used to specify preconditions, postconditions, exception guarantees, old 0149 value copies at body, and check class invariants for public functions that are 0150 not static, not virtual, and do not override: 0151 0152 @code 0153 class u { 0154 friend class boost::contract::access; 0155 0156 void invariant() const { // Optional (as for static and volatile). 0157 BOOST_CONTRACT_ASSERT(...); 0158 ... 0159 } 0160 0161 public: 0162 void f(...) { 0163 boost::contract::old_ptr<old_type> old_var; 0164 boost::contract::check c = boost::contract::public_function(this) 0165 .precondition([&] { // Optional. 0166 BOOST_CONTRACT_ASSERT(...); 0167 ... 0168 }) 0169 .old([&] { // Optional. 0170 old_var = BOOST_CONTRACT_OLDOF(old_expr); 0171 ... 0172 }) 0173 .postcondition([&] { // Optional. 0174 BOOST_CONTRACT_ASSERT(...); 0175 ... 0176 }) 0177 .except([&] { // Optional. 0178 BOOST_CONTRACT_ASSERT(...); 0179 ... 0180 }) 0181 ; 0182 0183 ... // Function body. 0184 } 0185 0186 ... 0187 }; 0188 @endcode 0189 0190 For optimization, this can be omitted for public functions that do not have 0191 preconditions, postconditions and exception guarantees, within classes that have 0192 no invariants. 0193 0194 @see @RefSect{tutorial.public_functions, Public Functions} 0195 0196 @param obj The object @c this from the scope of the enclosing public function 0197 declaring the contract. 0198 This object might be mutable, @c const, @c volatile, or 0199 <c>const volatile</c> depending on the cv-qualifier of the enclosing 0200 function (volatile public functions will check volatile class 0201 invariants, see 0202 @RefSect{extras.volatile_public_functions, 0203 Volatile Public Functions}). 0204 0205 @tparam Class The type of the class containing the public function declaring 0206 the contract. 0207 (Usually this template parameter is automatically deduced by C++ 0208 and it does not need to be explicitly specified by programmers.) 0209 0210 @return The result of this function must be assigned to a variable of type 0211 @RefClass{boost::contract::check} declared explicitly (i.e., without 0212 using C++11 @c auto declarations) and locally just before the code of 0213 the public function body (otherwise this library will generate a 0214 run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0215 */ 0216 template<class Class> 0217 specify_precondition_old_postcondition_except<> public_function(Class* obj) { 0218 #if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 0219 return specify_precondition_old_postcondition_except<>( 0220 new boost::contract::detail::public_function< 0221 boost::contract::detail::none, 0222 boost::contract::detail::none, 0223 boost::contract::detail::none, 0224 Class 0225 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( 0226 BOOST_CONTRACT_MAX_ARGS) 0227 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, 0228 BOOST_CONTRACT_MAX_ARGS, 0229 boost::contract::detail::none 0230 ) 0231 >( 0232 static_cast<boost::contract::virtual_*>(0), 0233 obj, 0234 boost::contract::detail::none::value() 0235 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( 0236 BOOST_CONTRACT_MAX_ARGS) 0237 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, 0238 BOOST_CONTRACT_MAX_ARGS, 0239 boost::contract::detail::none::value() 0240 ) 0241 ) 0242 ); 0243 #else 0244 return specify_precondition_old_postcondition_except<>(); 0245 #endif 0246 } 0247 0248 /** @cond */ 0249 0250 // For non-static, virtual, and non-overriding public functions (PRIVATE macro). 0251 #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( \ 0252 has_virtual_result) \ 0253 template< \ 0254 BOOST_PP_EXPR_IIF(has_virtual_result, typename VirtualResult) \ 0255 BOOST_PP_COMMA_IF(has_virtual_result) \ 0256 class Class \ 0257 > \ 0258 specify_precondition_old_postcondition_except< \ 0259 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)> \ 0260 public_function( \ 0261 virtual_* v \ 0262 BOOST_PP_COMMA_IF(has_virtual_result) \ 0263 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult& r) \ 0264 , Class* obj \ 0265 ) { \ 0266 BOOST_PP_IIF(BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_, \ 0267 /* no F... so cannot enforce contracted F returns VirtualResult */ \ 0268 return (specify_precondition_old_postcondition_except< \ 0269 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ 0270 new boost::contract::detail::public_function< \ 0271 boost::contract::detail::none, \ 0272 BOOST_PP_IIF(has_virtual_result, \ 0273 VirtualResult \ 0274 , \ 0275 boost::contract::detail::none \ 0276 ), \ 0277 boost::contract::detail::none, \ 0278 Class \ 0279 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( \ 0280 BOOST_CONTRACT_MAX_ARGS) \ 0281 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, \ 0282 BOOST_CONTRACT_MAX_ARGS, \ 0283 boost::contract::detail::none \ 0284 ) \ 0285 >( \ 0286 v, \ 0287 obj, \ 0288 BOOST_PP_IIF(has_virtual_result, \ 0289 r \ 0290 , \ 0291 boost::contract::detail::none::value() \ 0292 ) \ 0293 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( \ 0294 BOOST_CONTRACT_MAX_ARGS) \ 0295 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, \ 0296 BOOST_CONTRACT_MAX_ARGS, \ 0297 boost::contract::detail::none::value() \ 0298 ) \ 0299 ) \ 0300 )); \ 0301 , \ 0302 return specify_precondition_old_postcondition_except< \ 0303 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ 0304 ) \ 0305 } 0306 0307 /** @endcond */ 0308 0309 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN 0310 /** 0311 Program contracts for void virtual public functions that do not override. 0312 0313 This is used to specify preconditions, postconditions, exception guarantees, 0314 old value copies at body, and check class invariants for public functions 0315 that are virtual, do not override, and return @c void: 0316 0317 @code 0318 class u { 0319 friend class boost::contract::access; 0320 0321 void invariant() const { // Optional (as for static and volatile). 0322 BOOST_CONTRACT_ASSERT(...); 0323 ... 0324 } 0325 0326 public: 0327 void f(..., boost::contract::virtual_* v = 0) { 0328 boost::contract::old_ptr<old_type> old_var; 0329 boost::contract::check c = boost::contract::public_function(v, this) 0330 .precondition([&] { // Optional. 0331 BOOST_CONTRACT_ASSERT(...); 0332 ... 0333 }) 0334 .old([&] { // Optional. 0335 old_var = BOOST_CONTRACT_OLDOF(v, old_expr); 0336 ... 0337 }) 0338 .postcondition([&] { // Optional. 0339 BOOST_CONTRACT_ASSERT(...); 0340 ... 0341 }) 0342 .except([&] { // Optional. 0343 BOOST_CONTRACT_ASSERT(...); 0344 ... 0345 }) 0346 ; 0347 0348 ... // Function body. 0349 } 0350 0351 ... 0352 }; 0353 @endcode 0354 0355 A virtual public function should always call 0356 @RefFunc{boost::contract::public_function} otherwise this library will not 0357 be able to correctly use it for subcontracting. 0358 0359 @see @RefSect{tutorial.virtual_public_functions, Virtual Public Functions} 0360 0361 @param v The trailing parameter of type 0362 @RefClass{boost::contract::virtual_}<c>*</c> and default value 0363 @c 0 from the enclosing virtual public function. 0364 @param obj The object @c this from the scope of the enclosing virtual 0365 public function declaring the contract. 0366 This object might be mutable, @c const, @c volatile, or 0367 <c>const volatile</c> depending on the cv-qualifier of the 0368 enclosing function (volatile public functions will check 0369 volatile class invariants, see 0370 @RefSect{extras.volatile_public_functions, 0371 Volatile Public Functions}). 0372 0373 @tparam Class The type of the class containing the virtual public function 0374 declaring the contract. 0375 (Usually this template parameter is automatically deduced by 0376 C++ and it does not need to be explicitly specified by 0377 programmers.) 0378 0379 @return The result of this function must be assigned to a variable of type 0380 @RefClass{boost::contract::check} declared explicitly (i.e., without 0381 using C++11 @c auto declarations) and locally just before the code 0382 of the public function body (otherwise this library will generate a 0383 run-time error, see 0384 @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0385 */ 0386 template<class Class> 0387 specify_precondition_old_postcondition_except<> public_function( 0388 virtual_* v, Class* obj); 0389 0390 /** 0391 Program contracts for non-void virtual public functions that do not 0392 override. 0393 0394 This is used to specify preconditions, postconditions, exception guarantees, 0395 old value copies at body, and check class invariants for public functions 0396 that are virtual, do not override, and do not return @c void: 0397 0398 @code 0399 class u { 0400 friend class boost::contract::access; 0401 0402 void invariant() const { // Optional (as for static and volatile). 0403 BOOST_CONTRACT_ASSERT(...); 0404 ... 0405 } 0406 0407 public: 0408 t f(..., boost::contract::virtual_* v = 0) { 0409 t result; 0410 boost::contract::old_ptr<old_type> old_var; 0411 boost::contract::check c = boost::contract::public_function( 0412 v, result, this) 0413 .precondition([&] { // Optional. 0414 BOOST_CONTRACT_ASSERT(...); 0415 ... 0416 }) 0417 .old([&] { // Optional. 0418 old_var = BOOST_CONTRACT_OLDOF(v, old_expr); 0419 ... 0420 }) 0421 .postcondition([&] (t const& result) { // Optional. 0422 BOOST_CONTRACT_ASSERT(...); 0423 ... 0424 }) 0425 .except([&] { // Optional. 0426 BOOST_CONTRACT_ASSERT(...); 0427 ... 0428 }) 0429 ; 0430 0431 ... // Function body (use `return result = return_expr`). 0432 } 0433 0434 ... 0435 }; 0436 @endcode 0437 0438 A virtual public function should always call 0439 @RefFunc{boost::contract::public_function} otherwise this library will not 0440 be able to correctly use it for subcontracting. 0441 0442 @see @RefSect{tutorial.virtual_public_functions, Virtual Public Functions} 0443 0444 @param v The trailing parameter of type 0445 @RefClass{boost::contract::virtual_}<c>*</c> and default value 0446 @c 0 from the enclosing virtual public function. 0447 @param r A reference to the return value of the enclosing virtual public 0448 function declaring the contract. 0449 This is usually a local variable declared by the enclosing 0450 virtual public function just before the contract, but 0451 programmers must set it to the actual value being returned by 0452 the function at each @c return statement. 0453 @param obj The object @c this from the scope of the enclosing virtual 0454 public function declaring the contract. 0455 This object might be mutable, @c const, @c volatile, or 0456 <c>const volatile</c> depending on the cv-qualifier of the 0457 enclosing function (volatile public functions will check 0458 volatile class invariants, see 0459 @RefSect{extras.volatile_public_functions, 0460 Volatile Public Functions}). 0461 0462 @tparam VirtualResult This type must be the same as, or compatible with, 0463 the return type of the enclosing virtual public 0464 function declaring the contract (this library might 0465 not be able to generate a compile-time error if 0466 these types mismatch, but in general that will cause 0467 run-time errors or undefined behaviour). 0468 Alternatively, 0469 <c>boost::optional<<i>return-type</i>></c> can also 0470 be used (see 0471 @RefSect{advanced.optional_return_values, 0472 Optional Return Values}). 0473 (Usually this template parameter is automatically 0474 deduced by C++ and it does not need to be explicitly 0475 specified by programmers.) 0476 @tparam Class The type of the class containing the virtual public function 0477 declaring the contract. 0478 (Usually this template parameter is automatically deduced by 0479 C++ and it does not need to be explicitly specified by 0480 programmers.) 0481 0482 @return The result of this function must be assigned to a variable of type 0483 @RefClass{boost::contract::check} declared explicitly (i.e., without 0484 using C++11 @c auto declarations) and locally just before the code 0485 of the public function body (otherwise this library will generate a 0486 run-time error, see 0487 @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0488 */ 0489 template<typename VirtualResult, class Class> 0490 specify_precondition_old_postcondition_except<VirtualResult> 0491 public_function(virtual_* v, VirtualResult& r, Class* obj); 0492 #else 0493 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( 0494 /* has_virtual_result = */ 0) 0495 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( 0496 /* has_virtual_result = */ 1) 0497 #endif 0498 0499 /** @cond */ 0500 0501 // For non-static, virtual, and overriding public functions (PRIVATE macro). 0502 #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_( \ 0503 z, arity, arity_compl, has_virtual_result) \ 0504 BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ 0505 arity, /* is_friend = */ 0, has_virtual_result, \ 0506 Override, VirtualResult, F, Class, Args, \ 0507 v, r, /* f */ BOOST_PP_EMPTY(), obj, args \ 0508 ) { \ 0509 BOOST_PP_IIF(BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_, \ 0510 { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ 0511 /* assert not strictly necessary as compilation will fail */ \ 0512 /* anyways, but helps limiting cryptic compiler's errors */ \ 0513 BOOST_STATIC_ASSERT_MSG( \ 0514 /* -2 for both `this` and `virtual_*` extra parameters */ \ 0515 ( \ 0516 boost::function_types::function_arity<F>::value - 2 \ 0517 == \ 0518 BOOST_CONTRACT_DETAIL_TVARIADIC_SIZEOF(arity, Args) \ 0519 ), \ 0520 "missing one or more arguments for specified function" \ 0521 ); \ 0522 } \ 0523 { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ 0524 /* assert consistency of F's result type and VirtualResult */ \ 0525 BOOST_PP_IIF(has_virtual_result, \ 0526 BOOST_STATIC_ASSERT_MSG \ 0527 , \ 0528 BOOST_PP_TUPLE_EAT(2) \ 0529 )( \ 0530 (boost::is_same< \ 0531 typename boost::remove_reference<typename boost:: \ 0532 function_types::result_type<F>::type>::type, \ 0533 typename boost::contract::detail:: \ 0534 remove_value_reference_if_optional< \ 0535 VirtualResult \ 0536 >::type \ 0537 >::value), \ 0538 "mismatching result type for specified function" \ 0539 ); \ 0540 } \ 0541 { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ 0542 /* assert this so lib can check and enforce override */ \ 0543 BOOST_STATIC_ASSERT_MSG( \ 0544 boost::contract::access::has_base_types<Class>::value, \ 0545 "enclosing class missing 'base-types' typedef" \ 0546 ); \ 0547 } \ 0548 return (specify_precondition_old_postcondition_except< \ 0549 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ 0550 new boost::contract::detail::public_function< \ 0551 Override, \ 0552 BOOST_PP_IIF(has_virtual_result, \ 0553 VirtualResult \ 0554 , \ 0555 boost::contract::detail::none \ 0556 ), \ 0557 F, \ 0558 Class \ 0559 BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ 0560 BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, Args) \ 0561 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA(arity_compl) \ 0562 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(z, arity_compl, \ 0563 boost::contract::detail::none) \ 0564 >( \ 0565 v, \ 0566 obj, \ 0567 BOOST_PP_IIF(has_virtual_result, \ 0568 r \ 0569 , \ 0570 boost::contract::detail::none::value() \ 0571 ) \ 0572 BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ 0573 BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, args) \ 0574 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA(arity_compl) \ 0575 BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(z, arity_compl, \ 0576 boost::contract::detail::none::value()) \ 0577 ) \ 0578 )); \ 0579 , \ 0580 return specify_precondition_old_postcondition_except< \ 0581 BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ 0582 ) \ 0583 } 0584 0585 /** @endcond */ 0586 0587 #ifdef BOOST_CONTRACT_DETAIL_DOXYGEN 0588 /** 0589 Program contracts for void public functions overrides (virtual or not). 0590 0591 This is used to specify preconditions, postconditions, exception guarantees, 0592 old value copies at body, and check class invariants for public function 0593 overrides (virtual or not) that return @c void: 0594 0595 @code 0596 class u 0597 #define BASES private boost::contract::constructor_precondition<u>, \ 0598 public b, private w 0599 : BASES 0600 { 0601 friend class boost::contract::access; 0602 0603 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 0604 #undef BASES 0605 0606 void invariant() const { // Optional (as for static and volatile). 0607 BOOST_CONTRACT_ASSERT(...); 0608 ... 0609 } 0610 0611 BOOST_CONTRACT_OVERRIDES(f) 0612 0613 public: 0614 // Override from `b::f`. 0615 void f(t_1 a_1, ..., t_n a_n, boost::contract::virtual_* v = 0) { 0616 boost::contract::old_ptr<old_type> old_var; 0617 boost::contract::check c = boost::contract::public_function< 0618 override_f>(v, &u::f, this, a_1, ..., a_n) 0619 .precondition([&] { // Optional. 0620 BOOST_CONTRACT_ASSERT(...); 0621 ... 0622 }) 0623 .old([&] { // Optional. 0624 old_var = BOOST_CONTRACT_OLDOF(v, old_expr); 0625 ... 0626 }) 0627 .postcondition([&] { // Optional. 0628 BOOST_CONTRACT_ASSERT(...); 0629 ... 0630 }) 0631 .except([&] { // Optional. 0632 BOOST_CONTRACT_ASSERT(...); 0633 ... 0634 }) 0635 ; 0636 0637 ... // Function body. 0638 } 0639 0640 ... 0641 }; 0642 @endcode 0643 0644 A public function override should always call 0645 @RefFunc{boost::contract::public_function} otherwise this library will not 0646 be able to correctly use it for subcontracting. 0647 0648 @see @RefSect{tutorial.public_function_overrides__subcontracting_, 0649 Public Function Overrides} 0650 0651 @param v The trailing parameter of type 0652 @RefClass{boost::contract::virtual_}<c>*</c> and default value 0653 @c 0 from the enclosing public function override. 0654 @param f A pointer to the enclosing public function override declaring 0655 the contract (but see @RefSect{advanced.function_overloads, 0656 Function Overloads}). 0657 @param obj The object @c this from the scope of the enclosing public 0658 function override declaring the contract. 0659 This object might be mutable, @c const, @c volatile, or 0660 <c>const volatile</c> depending on the cv-qualifier of the 0661 enclosing function (volatile public functions will check 0662 volatile class invariants, see 0663 @RefSect{extras.volatile_public_functions, 0664 Volatile Public Functions}). 0665 @param args All arguments passed to the enclosing public function override 0666 declaring the contract (by reference and in the order they 0667 appear in the enclosing function declaration), but excluding the 0668 trailing argument @c v. 0669 0670 @tparam Override The type trait <c>override_<i>function-name</i></c> 0671 declared using the @RefMacro{BOOST_CONTRACT_OVERRIDE} or 0672 related macros. 0673 This template parameter must be explicitly specified 0674 (because there is no function argument from which it can 0675 be automatically deduced by C++). 0676 @tparam F The function pointer type of the enclosing public function 0677 override declaring the contract. 0678 (Usually this template parameter is automatically deduced by 0679 C++ and it does not need to be explicitly specified by 0680 programmers.) 0681 @tparam Class The type of the class containing the virtual public function 0682 declaring the contract. 0683 (Usually this template parameter is automatically deduced by 0684 C++ and it does not need to be explicitly specified by 0685 programmers.) 0686 @tparam Args The types of all parameters passed to the enclosing public 0687 function override declaring the contract, but excluding the 0688 trailing parameter type <c>boost::contract::virtual_*</c>. 0689 On compilers that do not support variadic templates, this 0690 library internally implements this function using 0691 preprocessor meta-programming (in this case, the maximum 0692 number of supported arguments is defined by 0693 @RefMacro{BOOST_CONTRACT_MAX_ARGS}). 0694 (Usually these template parameters are automatically deduced 0695 by C++ and they do not need to be explicitly specified by 0696 programmers.) 0697 0698 @return The result of this function must be assigned to a variable of type 0699 @RefClass{boost::contract::check} declared explicitly (i.e., without 0700 using C++11 @c auto declarations) and locally just before the code 0701 of the public function body (otherwise this library will generate a 0702 run-time error, see 0703 @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0704 */ 0705 template<class Override, typename F, class Class, typename... Args> 0706 specify_precondition_old_postcondition_except<> public_function( 0707 virtual_* v, F f, Class* obj, Args&... args); 0708 0709 /** 0710 Program contracts for non-void public functions overrides (virtual or not). 0711 0712 This is used to specify preconditions, postconditions, exception guarantees, 0713 old value copies at body, and check class invariants for public function 0714 overrides (virtual or not) that do not return @c void: 0715 0716 @code 0717 class u 0718 #define BASES private boost::contract::constructor_precondition<u>, \ 0719 public b, private w 0720 : BASES 0721 { 0722 friend class boost::contract::access; 0723 0724 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 0725 #undef BASES 0726 0727 void invariant() const { // Optional (as for static and volatile). 0728 BOOST_CONTRACT_ASSERT(...); 0729 ... 0730 } 0731 0732 BOOST_CONTRACT_OVERRIDES(f) 0733 0734 public: 0735 // Override from `b::f`. 0736 t f(t_1 a_1, ..., t_n a_n, boost::contract::virtual_* v = 0) { 0737 t result; 0738 boost::contract::old_ptr<old_type> old_var; 0739 boost::contract::check c = boost::contract::public_function< 0740 override_f>(v, result, &u::f, this, a_1, ..., a_n) 0741 .precondition([&] { // Optional. 0742 BOOST_CONTRACT_ASSERT(...); 0743 ... 0744 }) 0745 .old([&] { // Optional. 0746 old_var = BOOST_CONTRACT_OLDOF(v, old_expr); 0747 ... 0748 }) 0749 .postcondition([&] (t const& result) { // Optional. 0750 BOOST_CONTRACT_ASSERT(...); 0751 ... 0752 }) 0753 .except([&] { // Optional. 0754 BOOST_CONTRACT_ASSERT(...); 0755 ... 0756 }) 0757 ; 0758 0759 ... // Function body (use `return result = return_expr`). 0760 } 0761 0762 ... 0763 }; 0764 @endcode 0765 0766 A public function override should always call 0767 @RefFunc{boost::contract::public_function} otherwise this library will not 0768 be able to correctly use it for subcontracting. 0769 0770 @see @RefSect{tutorial.public_function_overrides__subcontracting_, 0771 Public Function Overrides} 0772 0773 @param v The trailing parameter of type 0774 @RefClass{boost::contract::virtual_}<c>*</c> and default value 0775 @c 0 from the enclosing public function override. 0776 @param r A reference to the return value of the enclosing public function 0777 override declaring the contract. 0778 This is usually a local variable declared by the enclosing 0779 public function override just before the contract, but 0780 programmers must set it to the actual value being returned by 0781 the function at each @c return statement. 0782 @param f A pointer to the enclosing public function override declaring 0783 the contract (but see @RefSect{advanced.function_overloads, 0784 Function Overloads}). 0785 @param obj The object @c this from the scope of the enclosing public 0786 function override declaring the contract. 0787 This object might be mutable, @c const, @c volatile, or 0788 <c>const volatile</c> depending on the cv-qualifier of the 0789 enclosing function (volatile public functions will check 0790 volatile class invariants, see 0791 @RefSect{extras.volatile_public_functions, 0792 Volatile Public Functions}). 0793 @param args All arguments passed to the enclosing public function override 0794 declaring the contract (by reference and in the order they 0795 appear in the enclosing function declaration), but excluding the 0796 trailing argument @c v. 0797 0798 @tparam Override The type trait <c>override_<i>function-name</i></c> 0799 declared using the @RefMacro{BOOST_CONTRACT_OVERRIDE} or 0800 related macros. 0801 This template parameter must be explicitly specified 0802 (because there is no function argument from which it can 0803 be automatically deduced by C++). 0804 @tparam VirtualResult This type must be the same as, or compatible with, 0805 the return type of the enclosing public function 0806 override declaring the contract (this library might 0807 not be able to generate a compile-time error if 0808 these types mismatch, but in general that will cause 0809 run-time errors or undefined behaviour). 0810 Alternatively, 0811 <c>boost::optional<<i>return-type</i>></c> can also 0812 be used (see 0813 @RefSect{advanced.optional_return_values, 0814 Optional Return Values}). 0815 (Usually this template parameter is automatically 0816 deduced by C++ and it does not need to be explicitly 0817 specified by programmers.) 0818 @tparam F The function pointer type of the enclosing public function 0819 override declaring the contract. 0820 (Usually this template parameter is automatically deduced by 0821 C++ and it does not need to be explicitly specified by 0822 programmers.) 0823 @tparam Class The type of the class containing the virtual public function 0824 declaring the contract. 0825 (Usually this template parameter is automatically deduced by 0826 C++ and it does not need to be explicitly specified by 0827 programmers.) 0828 @tparam Args The types of all parameters passed to the enclosing public 0829 function override declaring the contract, but excluding the 0830 trailing parameter type <c>boost::contract::virtual_*</c>. 0831 On compilers that do not support variadic templates, this 0832 library internally implements this function using 0833 preprocessor meta-programming (in this case, the maximum 0834 number of supported arguments is defined by 0835 @RefMacro{BOOST_CONTRACT_MAX_ARGS}). 0836 (Usually these template parameters are automatically deduced 0837 by C++ and they do not need to be explicitly specified by 0838 programmers.) 0839 0840 @return The result of this function must be assigned to a variable of type 0841 @RefClass{boost::contract::check} declared explicitly (i.e., without 0842 using C++11 @c auto declarations) and locally just before the code 0843 of the public function body (otherwise this library will generate a 0844 run-time error, see 0845 @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). 0846 */ 0847 template<class Override, typename VirtualResult, typename F, class Class, 0848 typename... Args> 0849 specify_precondition_old_postcondition_except<VirtualResult> 0850 public_function(virtual_* v, VirtualResult& r, F f, Class* obj, 0851 Args&... args); 0852 0853 #elif BOOST_CONTRACT_DETAIL_TVARIADIC 0854 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(1, /* arity = */ ~, 0855 /* arity_compl = */ ~, /* has_virtual_result = */ 0) 0856 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(1, /* arity = */ ~, 0857 /* arity_compl = */ ~, /* has_virtual_result = */ 1) 0858 0859 #else 0860 /* PRIVATE */ 0861 0862 #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_ARITY_( \ 0863 z, arity, unused) \ 0864 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDES_(z, arity, \ 0865 BOOST_PP_SUB(BOOST_CONTRACT_MAX_ARGS, arity), ~) 0866 0867 #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDES_(z, \ 0868 arity, arity_compl, unused) \ 0869 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ 0870 arity, arity_compl, /* has_virtual_result = */ 0) \ 0871 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ 0872 arity, arity_compl, /* has_virtual_result = */ 1) 0873 0874 /* CODE */ 0875 0876 BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), 0877 BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_ARITY_, ~) 0878 #endif 0879 0880 } } // namespace 0881 0882 #endif // #include guard 0883
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|