diff options
Diffstat (limited to 'boost/contract/public_function.hpp')
-rw-r--r-- | boost/contract/public_function.hpp | 876 |
1 files changed, 876 insertions, 0 deletions
diff --git a/boost/contract/public_function.hpp b/boost/contract/public_function.hpp new file mode 100644 index 0000000000..f66e666cb9 --- /dev/null +++ b/boost/contract/public_function.hpp @@ -0,0 +1,876 @@ + +#ifndef BOOST_CONTRACT_PUBLIC_FUNCTION_HPP_ +#define BOOST_CONTRACT_PUBLIC_FUNCTION_HPP_ + +// Copyright (C) 2008-2018 Lorenzo Caminiti +// Distributed under the Boost Software License, Version 1.0 (see accompanying +// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt). +// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html + +/** @file +Program contracts for public functions (including subcontracting). +Overloads handle public functions that are static, virtual void, virtual non-void, overriding void, and overriding non-void. +*/ + +#include <boost/contract/core/config.hpp> +#include <boost/contract/core/specify.hpp> +#include <boost/contract/core/access.hpp> +#include <boost/contract/core/virtual.hpp> +/** @cond */ +// Needed within macro expansions below instead of defined(...) (PRIVATE macro). +#if !defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS) || \ + defined(BOOST_CONTRACT_STATIC_LINK) + #define BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 1 +#else + #define BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ 0 +#endif +/** @endcond */ +#include <boost/contract/detail/decl.hpp> +#include <boost/contract/detail/tvariadic.hpp> +#if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ + #include <boost/contract/detail/operation/static_public_function.hpp> + #include <boost/contract/detail/operation/public_function.hpp> + #include <boost/contract/detail/type_traits/optional.hpp> + #include <boost/contract/detail/none.hpp> + #include <boost/function_types/result_type.hpp> + #include <boost/function_types/function_arity.hpp> + #include <boost/optional.hpp> + #include <boost/type_traits/remove_reference.hpp> + #include <boost/type_traits/is_same.hpp> + #include <boost/static_assert.hpp> + #include <boost/preprocessor/tuple/eat.hpp> +#endif +#if !BOOST_CONTRACT_DETAIL_TVARIADIC + #include <boost/preprocessor/repetition/repeat.hpp> + #include <boost/preprocessor/arithmetic/sub.hpp> + #include <boost/preprocessor/arithmetic/inc.hpp> +#endif +#include <boost/preprocessor/control/expr_iif.hpp> +#include <boost/preprocessor/control/iif.hpp> +#include <boost/preprocessor/punctuation/comma_if.hpp> + +namespace boost { namespace contract { + +// NOTE: Override and (optionally) VirtualResult allowed only when v is present +// because: +// * An overriding func must override a base func declared virtual so with +// v extra param, thus the overriding func must also always have v (i.e., +// Override might be present only if v is also present). However, the first +// appearing virtual func (e.g., in root class) will not override any +// previously declared virtual func so does not need Override (i.e., Override +// always optional). +// Furthermore, F needs to be specified only together with Override. +// * VirtualResult is only used for virtual functions (i.e., VirtualResult might +// be present only if v is also present). +// However, VirtualResult is never specified, not even for virtual functions, +// when the return type is void (i.e., VirtualResult always optional). + +/** +Program contracts for static public functions. + +This is used to specify preconditions, postconditions, exception guarantees, old +value copies at body, and check static class invariants for static public +functions: + +@code +class u { + friend class boost::contract::access; + + static void static_invariant() { // Optional (as for non-static). + BOOST_CONTRACT_ASSERT(...); + ... + } + +public: + static void f(...) { + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function<u>() + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(old_expr); + ... + }) + .postcondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body. + } + + ... +}; +@endcode + +For optimization, this can be omitted for static public functions that do not +have preconditions, postconditions and exception guarantees, within classes that +have no static invariants. + +@see @RefSect{tutorial.static_public_functions, Static Public Functions} + +@tparam Class The type of the class containing the static public function + declaring the contract. + This template parameter must be explicitly specified for static + public functions (because they have no object @c this so there + is no function argument from which this type template parameter + can be deduced by this library). + +@return The result of this function must be explicitly assigned to a variable of + type @RefClass{boost::contract::check} declared locally just before the + code of the static function body (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). +*/ +template<class Class> +specify_precondition_old_postcondition_except<> public_function() { + #if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ + return specify_precondition_old_postcondition_except<>( + new boost::contract::detail::static_public_function<Class>()); + #else + return specify_precondition_old_postcondition_except<>(); + #endif +} + +/** +Program contracts for public functions that are not static, not virtual, and do +not not override. + +This is used to specify preconditions, postconditions, exception guarantees, old +value copies at body, and check class invariants for public functions that are +not static, not virtual, and do not override: + +@code +class u { + friend class boost::contract::access; + + void invariant() const { // Optional (as for static and volatile). + BOOST_CONTRACT_ASSERT(...); + ... + } + +public: + void f(...) { + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function(this) + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(old_expr); + ... + }) + .postcondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body. + } + + ... +}; +@endcode + +For optimization, this can be omitted for public functions that do not have +preconditions, postconditions and exception guarantees, within classes that have +no invariants. + +@see @RefSect{tutorial.public_functions, Public Functions} + +@param obj The object @c this from the scope of the enclosing public function + declaring the contract. + This object might be mutable, @c const, @c volatile, or + <c>const volatile</c> depending on the cv-qualifier of the enclosing + function (volatile public functions will check volatile class + invariants, see + @RefSect{extras.volatile_public_functions, + Volatile Public Functions}). + +@tparam Class The type of the class containing the public function declaring + the contract. + (Usually this template parameter is automatically deduced by C++ + and it does not need to be explicitly specified by programmers.) + +@return The result of this function must be explicitly assigned to a variable of + type @RefClass{boost::contract::check} declared locally just before the + code of the public function body (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). +*/ +template<class Class> +specify_precondition_old_postcondition_except<> public_function(Class* obj) { + #if BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_ + return specify_precondition_old_postcondition_except<>( + new boost::contract::detail::public_function< + boost::contract::detail::none, + boost::contract::detail::none, + boost::contract::detail::none, + Class + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( + BOOST_CONTRACT_MAX_ARGS) + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, + BOOST_CONTRACT_MAX_ARGS, + boost::contract::detail::none + ) + >( + static_cast<boost::contract::virtual_*>(0), + obj, + boost::contract::detail::none::value() + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( + BOOST_CONTRACT_MAX_ARGS) + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, + BOOST_CONTRACT_MAX_ARGS, + boost::contract::detail::none::value() + ) + ) + ); + #else + return specify_precondition_old_postcondition_except<>(); + #endif +} + +/** @cond */ + +// For non-static, virtual, and non-overriding public functions (PRIVATE macro). +#define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( \ + has_virtual_result) \ + template< \ + BOOST_PP_EXPR_IIF(has_virtual_result, typename VirtualResult) \ + BOOST_PP_COMMA_IF(has_virtual_result) \ + class Class \ + > \ + specify_precondition_old_postcondition_except< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)> \ + public_function( \ + virtual_* v \ + BOOST_PP_COMMA_IF(has_virtual_result) \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult& r) \ + , Class* obj \ + ) { \ + BOOST_PP_IIF(BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_, \ + /* no F... so cannot enforce contracted F returns VirtualResult */ \ + return (specify_precondition_old_postcondition_except< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ + new boost::contract::detail::public_function< \ + boost::contract::detail::none, \ + BOOST_PP_IIF(has_virtual_result, \ + VirtualResult \ + , \ + boost::contract::detail::none \ + ), \ + boost::contract::detail::none, \ + Class \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( \ + BOOST_CONTRACT_MAX_ARGS) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, \ + BOOST_CONTRACT_MAX_ARGS, \ + boost::contract::detail::none \ + ) \ + >( \ + v, \ + obj, \ + BOOST_PP_IIF(has_virtual_result, \ + r \ + , \ + boost::contract::detail::none::value() \ + ) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( \ + BOOST_CONTRACT_MAX_ARGS) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, \ + BOOST_CONTRACT_MAX_ARGS, \ + boost::contract::detail::none::value() \ + ) \ + ) \ + )); \ + , \ + return specify_precondition_old_postcondition_except< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ + ) \ + } + +/** @endcond */ + +#ifdef BOOST_CONTRACT_DETAIL_DOXYGEN + /** + Program contracts for void virtual public functions that do not override. + + This is used to specify preconditions, postconditions, exception guarantees, + old value copies at body, and check class invariants for public functions + that are virtual, do not override, and return @c void: + + @code + class u { + friend class boost::contract::access; + + void invariant() const { // Optional (as for static and volatile). + BOOST_CONTRACT_ASSERT(...); + ... + } + + public: + void f(..., boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function(v, this) + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(v, old_expr); + ... + }) + .postcondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body. + } + + ... + }; + @endcode + + A virtual public function should always call + @RefFunc{boost::contract::public_function} otherwise this library will not + be able to correctly use it for subcontracting. + + @see @RefSect{tutorial.virtual_public_functions, Virtual Public Functions} + + @param v The trailing parameter of type + @RefClass{boost::contract::virtual_}<c>*</c> and default value + @c 0 from the enclosing virtual public function. + @param obj The object @c this from the scope of the enclosing virtual + public function declaring the contract. + This object might be mutable, @c const, @c volatile, or + <c>const volatile</c> depending on the cv-qualifier of the + enclosing function (volatile public functions will check + volatile class invariants, see + @RefSect{extras.volatile_public_functions, + Volatile Public Functions}). + + @tparam Class The type of the class containing the virtual public function + declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers.) + + @return The result of this function must be explicitly assigned to a + variable of type @RefClass{boost::contract::check} declared locally + just before the code of the public function body (otherwise this + library will generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). + */ + template<class Class> + specify_precondition_old_postcondition_except<> public_function( + virtual_* v, Class* obj); + + /** + Program contracts for non-void virtual public functions that do not + override. + + This is used to specify preconditions, postconditions, exception guarantees, + old value copies at body, and check class invariants for public functions + that are virtual, do not override, and do not return @c void: + + @code + class u { + friend class boost::contract::access; + + void invariant() const { // Optional (as for static and volatile). + BOOST_CONTRACT_ASSERT(...); + ... + } + + public: + t f(..., boost::contract::virtual_* v = 0) { + t result; + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function( + v, result, this) + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(v, old_expr); + ... + }) + .postcondition([&] (t const& result) { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body (use `return result = return_expr`). + } + + ... + }; + @endcode + + A virtual public function should always call + @RefFunc{boost::contract::public_function} otherwise this library will not + be able to correctly use it for subcontracting. + + @see @RefSect{tutorial.virtual_public_functions, Virtual Public Functions} + + @param v The trailing parameter of type + @RefClass{boost::contract::virtual_}<c>*</c> and default value + @c 0 from the enclosing virtual public function. + @param r A reference to the return value of the enclosing virtual public + function declaring the contract. + This is usually a local variable declared by the enclosing + virtual public function just before the contract, but + programmers must set it to the actual value being returned by + the function at each @c return statement. + @param obj The object @c this from the scope of the enclosing virtual + public function declaring the contract. + This object might be mutable, @c const, @c volatile, or + <c>const volatile</c> depending on the cv-qualifier of the + enclosing function (volatile public functions will check + volatile class invariants, see + @RefSect{extras.volatile_public_functions, + Volatile Public Functions}). + + @tparam VirtualResult This type must be the same as, or compatible with, + the return type of the enclosing virtual public + function declaring the contract (this library might + not be able to generate a compile-time error if + these types mismatch, but in general that will cause + run-time errors or undefined behaviour). + Alternatively, + <c>boost::optional<<i>return-type</i>></c> can also + be used (see + @RefSect{advanced.optional_return_values, + Optional Return Values}). + (Usually this template parameter is automatically + deduced by C++ and it does not need to be explicitly + specified by programmers.) + @tparam Class The type of the class containing the virtual public function + declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers.) + + @return The result of this function must be explicitly assigned to a + variable of type @RefClass{boost::contract::check} declared locally + just before the code of the public function body (otherwise this + library will generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). + */ + template<typename VirtualResult, class Class> + specify_precondition_old_postcondition_except<VirtualResult> + public_function(virtual_* v, VirtualResult& r, Class* obj); +#else + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( + /* has_virtual_result = */ 0) + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( + /* has_virtual_result = */ 1) +#endif + +/** @cond */ + +// For non-static, virtual, and overriding public functions (PRIVATE macro). +#define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_( \ + z, arity, arity_compl, has_virtual_result) \ + BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ + arity, /* is_friend = */ 0, has_virtual_result, \ + Override, VirtualResult, F, Class, Args, \ + v, r, f, obj, args \ + ) { \ + BOOST_PP_IIF(BOOST_CONTRACT_PUBLIC_FUNCTIONS_IMPL_, \ + { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ + /* assert not strictly necessary as compilation will fail */ \ + /* anyways, but helps limiting cryptic compiler's errors */ \ + BOOST_STATIC_ASSERT_MSG( \ + /* -2 for both `this` and `virtual_*` extra parameters */ \ + ( \ + boost::function_types::function_arity<F>::value - 2 \ + == \ + BOOST_CONTRACT_DETAIL_TVARIADIC_SIZEOF(arity, Args) \ + ), \ + "missing one or more arguments for specified function" \ + ); \ + } \ + { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ + /* assert consistency of F's result type and VirtualResult */ \ + BOOST_PP_IIF(has_virtual_result, \ + BOOST_STATIC_ASSERT_MSG \ + , \ + BOOST_PP_TUPLE_EAT(2) \ + )( \ + (boost::is_same< \ + typename boost::remove_reference<typename boost:: \ + function_types::result_type<F>::type>::type, \ + typename boost::contract::detail:: \ + remove_value_reference_if_optional< \ + VirtualResult \ + >::type \ + >::value), \ + "mismatching result type for specified function" \ + ); \ + } \ + { /* extra scope paren to expand STATIC_STATIC emu on same line */ \ + /* assert this so lib can check and enforce override */ \ + BOOST_STATIC_ASSERT_MSG( \ + boost::contract::access::has_base_types<Class>::value, \ + "enclosing class missing 'base-types' typedef" \ + ); \ + } \ + return (specify_precondition_old_postcondition_except< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ + new boost::contract::detail::public_function< \ + Override, \ + BOOST_PP_IIF(has_virtual_result, \ + VirtualResult \ + , \ + boost::contract::detail::none \ + ), \ + F, \ + Class \ + BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ + BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, Args) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA(arity_compl) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(z, arity_compl, \ + boost::contract::detail::none) \ + >( \ + v, \ + obj, \ + BOOST_PP_IIF(has_virtual_result, \ + r \ + , \ + boost::contract::detail::none::value() \ + ) \ + BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ + BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, args) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA(arity_compl) \ + BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(z, arity_compl, \ + boost::contract::detail::none::value()) \ + ) \ + )); \ + , \ + return specify_precondition_old_postcondition_except< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ + ) \ + } + +/** @endcond */ + +#ifdef BOOST_CONTRACT_DETAIL_DOXYGEN + /** + Program contracts for void public functions overrides (virtual or not). + + This is used to specify preconditions, postconditions, exception guarantees, + old value copies at body, and check class invariants for public function + overrides (virtual or not) that return @c void: + + @code + class u + #define BASES private boost::contract::constructor_precondition<u>, \ + public b, private w + : BASES + { + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { // Optional (as for static and volatile). + BOOST_CONTRACT_ASSERT(...); + ... + } + + BOOST_CONTRACT_OVERRIDES(f) + + public: + // Override from `b::f`. + void f(t_1 a_1, ..., t_n a_n, boost::contract::virtual_* v = 0) { + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function< + override_f>(v, &u::f, this, a_1, ..., a_n) + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(v, old_expr); + ... + }) + .postcondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body. + } + + ... + }; + @endcode + + A public function override should always call + @RefFunc{boost::contract::public_function} otherwise this library will not + be able to correctly use it for subcontracting. + + @see @RefSect{tutorial.public_function_overrides__subcontracting_, + Public Function Overrides} + + @param v The trailing parameter of type + @RefClass{boost::contract::virtual_}<c>*</c> and default value + @c 0 from the enclosing public function override. + @param f A pointer to the enclosing public function override declaring + the contract. + @param obj The object @c this from the scope of the enclosing public + function override declaring the contract. + This object might be mutable, @c const, @c volatile, or + <c>const volatile</c> depending on the cv-qualifier of the + enclosing function (volatile public functions will check + volatile class invariants, see + @RefSect{extras.volatile_public_functions, + Volatile Public Functions}). + @param args All arguments passed to the enclosing public function override + declaring the contract (by reference and in the order they + appear in the enclosing function declaration), but excluding the + trailing argument @c v. + + @tparam Override The type <c>override_<i>function-name</i></c> declared + using the @RefMacro{BOOST_CONTRACT_OVERRIDE} or related + macros. + This template parameter must be explicitly specified + (because there is no function argument from which it can + be automatically deduced by C++). + @tparam F The function pointer type of the enclosing public function + override declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers, but see + @RefSect{advanced.function_overloads, Function Overloads}.) + @tparam Class The type of the class containing the virtual public function + declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers.) + @tparam Args The types of all parameters passed to the enclosing public + function override declaring the contract, but excluding the + trailing parameter type <c>boost::contract::virtual_*</c>. + On compilers that do not support variadic templates, this + library internally implements this function using + preprocessor meta-programming (in this case, the maximum + number of supported arguments is defined by + @RefMacro{BOOST_CONTRACT_MAX_ARGS}). + (Usually these template parameters are automatically deduced + by C++ and they do not need to be explicitly specified by + programmers.) + + @return The result of this function must be explicitly assigned to a + variable of type @RefClass{boost::contract::check} declared locally + just before the code of the public function body (otherwise this + library will generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). + */ + template<class Override, typename F, class Class, typename... Args> + specify_precondition_old_postcondition_except<> public_function( + virtual_* v, F f, Class* obj, Args&... args); + + /** + Program contracts for non-void public functions overrides (virtual or not). + + This is used to specify preconditions, postconditions, exception guarantees, + old value copies at body, and check class invariants for public function + overrides (virtual or not) that do not return @c void: + + @code + class u + #define BASES private boost::contract::constructor_precondition<u>, \ + public b, private w + : BASES + { + friend class boost::contract::access; + + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + void invariant() const { // Optional (as for static and volatile). + BOOST_CONTRACT_ASSERT(...); + ... + } + + BOOST_CONTRACT_OVERRIDES(f) + + public: + // Override from `b::f`. + t f(t_1 a_1, ..., t_n a_n, boost::contract::virtual_* v = 0) { + t result; + boost::contract::old_ptr<old_type> old_var; + boost::contract::check c = boost::contract::public_function< + override_f>(v, result, &u::f, this, a_1, ..., a_n) + .precondition([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .old([&] { // Optional. + old_var = BOOST_CONTRACT_OLDOF(v, old_expr); + ... + }) + .postcondition([&] (t const& result) { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + .except([&] { // Optional. + BOOST_CONTRACT_ASSERT(...); + ... + }) + ; + + ... // Function body (use `return result = return_expr`). + } + + ... + }; + @endcode + + A public function override should always call + @RefFunc{boost::contract::public_function} otherwise this library will not + be able to correctly use it for subcontracting. + + @see @RefSect{tutorial.public_function_overrides__subcontracting_, + Public Function Overrides} + + @param v The trailing parameter of type + @RefClass{boost::contract::virtual_}<c>*</c> and default value + @c 0 from the enclosing public function override. + @param r A reference to the return value of the enclosing public function + override declaring the contract. + This is usually a local variable declared by the enclosing + public function override just before the contract, but + programmers must set it to the actual value being returned by + the function at each @c return statement. + @param f A pointer to the enclosing public function override declaring + the contract. + @param obj The object @c this from the scope of the enclosing public + function override declaring the contract. + This object might be mutable, @c const, @c volatile, or + <c>const volatile</c> depending on the cv-qualifier of the + enclosing function (volatile public functions will check + volatile class invariants, see + @RefSect{extras.volatile_public_functions, + Volatile Public Functions}). + @param args All arguments passed to the enclosing public function override + declaring the contract (by reference and in the order they + appear in the enclosing function declaration), but excluding the + trailing argument @c v. + + @tparam Override The type <c>override_<i>function-name</i></c> declared + using the @RefMacro{BOOST_CONTRACT_OVERRIDE} or related + macros. + This template parameter must be explicitly specified + (because there is no function argument from which it can + be automatically deduced by C++). + @tparam VirtualResult This type must be the same as, or compatible with, + the return type of the enclosing public function + override declaring the contract (this library might + not be able to generate a compile-time error if + these types mismatch, but in general that will cause + run-time errors or undefined behaviour). + Alternatively, + <c>boost::optional<<i>return-type</i>></c> can also + be used (see + @RefSect{advanced.optional_return_values, + Optional Return Values}). + (Usually this template parameter is automatically + deduced by C++ and it does not need to be explicitly + specified by programmers.) + @tparam F The function pointer type of the enclosing public function + override declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers, but see + @RefSect{advanced.function_overloads, + Function Overloads}.) + @tparam Class The type of the class containing the virtual public function + declaring the contract. + (Usually this template parameter is automatically deduced by + C++ and it does not need to be explicitly specified by + programmers.) + @tparam Args The types of all parameters passed to the enclosing public + function override declaring the contract, but excluding the + trailing parameter type <c>boost::contract::virtual_*</c>. + On compilers that do not support variadic templates, this + library internally implements this function using + preprocessor meta-programming (in this case, the maximum + number of supported arguments is defined by + @RefMacro{BOOST_CONTRACT_MAX_ARGS}). + (Usually these template parameters are automatically deduced + by C++ and they do not need to be explicitly specified by + programmers.) + + @return The result of this function must be explicitly assigned to a + variable of type @RefClass{boost::contract::check} declared locally + just before the code of the public function body (otherwise this + library will generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_CHECK_DECL}). + */ + template<class Override, typename VirtualResult, typename F, class Class, + typename... Args> + specify_precondition_old_postcondition_except<VirtualResult> + public_function(virtual_* v, VirtualResult& r, F f, Class* obj, + Args&... args); + +#elif BOOST_CONTRACT_DETAIL_TVARIADIC + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(1, /* arity = */ ~, + /* arity_compl = */ ~, /* has_virtual_result = */ 0) + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(1, /* arity = */ ~, + /* arity_compl = */ ~, /* has_virtual_result = */ 1) + +#else + /* PRIVATE */ + + #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_ARITY_( \ + z, arity, unused) \ + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDES_(z, arity, \ + BOOST_PP_SUB(BOOST_CONTRACT_MAX_ARGS, arity), ~) + + #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDES_(z, \ + arity, arity_compl, unused) \ + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ + arity, arity_compl, /* has_virtual_result = */ 0) \ + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ + arity, arity_compl, /* has_virtual_result = */ 1) + + /* CODE */ + + BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), + BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_ARITY_, ~) +#endif + +} } // namespace + +#endif // #include guard + |