diff --git a/doc/Jamfile.v2 b/doc/Jamfile.v2 index 777b0df..30b5fea 100644 --- a/doc/Jamfile.v2 +++ b/doc/Jamfile.v2 @@ -15,25 +15,22 @@ doxygen reference ../include/boost/contract/old.hpp ../include/boost/contract/call_if.hpp + ../include/boost/contract/core/specify.hpp ../include/boost/contract/core/access.hpp ../include/boost/contract/core/virtual.hpp - ../include/boost/contract/core/set_precondition_old_postcondition.hpp - ../include/boost/contract/core/set_old_postcondition.hpp - ../include/boost/contract/core/set_postcondition_only.hpp - ../include/boost/contract/core/set_nothing.hpp - ../include/boost/contract/core/exception.hpp ../include/boost/contract/core/config.hpp ../include/boost/contract.hpp : "Reference" # But Quickbook's Doxygen does not show destructor exception specs. - PREDEFINED="DOXYGEN BOOST_NOEXCEPT_OR_NOTHROW:=noexcept BOOST_NOEXCEPT_IF:=noexcept BOOST_PP_VARIADICS" + PREDEFINED="DOXYGEN BOOST_PP_VARIADICS" MACRO_EXPANSION=YES INCLUDE_PATH="../include" QUIET=YES JAVADOC_AUTOBRIEF=YES WARN_IF_UNDOCUMENTED=NO + EXCLUDE_SYMBOLS=std # Does not work for XML output (use @cond/#ifdef DOXYGEN in code instead). EXTRACT_PRIVATE=NO HIDE_UNDOC_MEMBERS=YES diff --git a/doc/advanced_topics.qbk b/doc/advanced_topics.qbk index c9114e9..ecfdbef 100644 --- a/doc/advanced_topics.qbk +++ b/doc/advanced_topics.qbk @@ -358,7 +358,7 @@ This implementation is much more concise, easy to read and maintain than the usu [endsect] -[section Access] +[section Access Specifiers] As seen so far, programmers are required to decorate their classes declaring extra members that are internally used by this library to check contracts: @@ -487,7 +487,7 @@ Also the [macroref BOOST_CONTRACT_NO_ENTRY_INVARIANTS] and [macroref BOOST_CONTR * The [macroref BOOST_CONTRACT_NO_DESTRUCTORS] macro is automatically defined by this library (a compile-time error will be reported if programmers try to manually define this macro) and it can be used in `#ifdef` statements to disable compilation of destructor contract guards. * The [macroref BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS] macro is automatically defined by this library (a compile-time error will be reported if programmers try to manually define this macro) and it can be used in `#ifdef` statements to disable compilation of public member function contract guards, base type `typedef`, extra [classref boost::contract::virtual_] function parameters, and [macroref BOOST_CONTRACT_OVERRIDE] declarations. * The [macroref BOOST_CONTRACT_NO_FUNCTIONS] macro is automatically defined by this library (a compile-time error will be reported if programmers try to manually define this macro) and it can be used in `#ifdef` statements to disable compilation of contract guards for non-member functions as well as private and protected functions. -* The [macroref BOOST_CONTRACT_NO_ALL] macro is automatically defined by this library (a compile-time error will be reported if programmers try to manually define this macro) and it can be used in `#ifdef` statements to disable [classref boost::contract::access] friendship declarations and also inclusions of [headerref contract.hpp] (some of the other macros listed here can be used to selectively disable inclusion of =boost/contract/*.hpp= headers when they are used instead of [headerref contract.hpp].) +* The [macroref BOOST_CONTRACT_NO_ALL] macro is automatically defined by this library (a compile-time error will be reported if programmers try to manually define this macro) and it can be used in `#ifdef` statements to disable [classref boost::contract::access] friendship declarations and also inclusions of [headerref boost/contract.hpp] (some of the other macros listed here can be used to selectively disable inclusion of =boost/contract/*.hpp= headers when they are used instead of [headerref boost/contract.hpp].) [endsect] diff --git a/doc/contract.qbk b/doc/contract.qbk index 770a9e4..85f5d43 100644 --- a/doc/contract.qbk +++ b/doc/contract.qbk @@ -46,10 +46,10 @@ [def __Old_Values_at_Body__ [link boost_contract.advanced_topics.old_values_at_body Old Values at Body]] [def __Optional_Return_Value__ [link boost_contract.advanced_topics.optional_return_value Optional Return Value]] [def __Pure_Virtual_Public_Functions__ [link boost_contract.advanced_topics.pure_virtual_public_functions Pure Virtual Public Functions]] -[def __Named_Overrides__ [link boost_contract.advanced_topics.overloads_and_named_overrides Named Overrides]] -[def __Volatile_Public_Functions__ [link boost_contract.advanced_topics.volatile_public_functions Volatile Public Functions]] +[def __Named_Overrides__ [link boost_contract.advanced_topics.named_overrides Named Overrides]] +[def __Volatile_Class_Invariants__ [link boost_contract.advanced_topics.volatile_class_invariants Volatile Class Invariants]] [def __Old_Value_Requirements__ [link boost_contract.advanced_topics.old_value_requirements Old Value Requirements]] -[def __Access__ [link boost_contract.advanced_topics.access Access]] +[def __Access_Specifiers__ [link boost_contract.advanced_topics.access_specifiers Access Specifiers]] [def __Separate_Body_Implementation__ [link boost_contract.advanced_topics.separate_body_implementation Separate Body Implementation]] [def __Throw_on_Failure__ [link boost_contract.advanced_topics.throw_on_failure Throw on Failure]] [def __Disable_Contract_Checking__ [link boost_contract.advanced_topics.disable_contract_checking Disable Contract Checking]] diff --git a/doc/contract_programming_overview.qbk b/doc/contract_programming_overview.qbk index 182710a..50d6e71 100644 --- a/doc/contract_programming_overview.qbk +++ b/doc/contract_programming_overview.qbk @@ -438,7 +438,7 @@ Therefore, this feature was removed in the current revision of this library. ][ [['Disable contract checking]] [ -Yes, contract checking can be skipped at run-time by defining combinations of the [macroref BOOST_CONTRACT_NO_PRECONDITIONS], [macroref BOOST_CONTRACT_NO_POSTCONDITIONS], [macroref BOOST_CONTRACT_NO_INVARIANTS], [macroref BOOST_CONTRACT_NO_ENTRY_INVARIATS], and [macroref BOOST_CONTRACT_NO_EXIT_INVARIANTS] macros. +Yes, contract checking can be skipped at run-time by defining combinations of the [macroref BOOST_CONTRACT_NO_PRECONDITIONS], [macroref BOOST_CONTRACT_NO_POSTCONDITIONS], [macroref BOOST_CONTRACT_NO_INVARIANTS], [macroref BOOST_CONTRACT_NO_ENTRY_INVARIANTS], and [macroref BOOST_CONTRACT_NO_EXIT_INVARIANTS] macros. (Also removing contract code from compiled object code is possible but requires users to program a fare amount of boiler-plate code, see __Disable_Contract_Checking__.) ] [Yes (contract code also removed from compiled object code).] diff --git a/doc/examples.qbk b/doc/examples.qbk index c667f47..6b79f3c 100644 --- a/doc/examples.qbk +++ b/doc/examples.qbk @@ -15,13 +15,14 @@ Sources: A few notable examples: -* [link contract__.examples.__n1962___vector__comparison_with_c___proposed_syntax \[N1962\] Vector]: Complete contracts for `std::vector` and a comparison with __N1962__ syntax. -* [link contract__.examples.__n1962___square_root__default_parameters_and_comparison_with_d_syntax \[N1962\] Square Root]: Comparison with D syntax. -* [link contract__.examples.__mitchell02___counter__subcontracting_and_virtual_specifiers__final__override__new__and_pure_virtual_ \[Mitchell02\] Counter]: Subcontracting. -* [link contract__.examples.__meyer97___stack4__comparison_with_eiffel_syntax \[Meyer97\] Stack4]: Comparison with Eiffel syntax. -* [link contract__.examples.__cline90___vector__comparison_with_a___proposed_syntax \[Cline90\] Vector]: Comparison with A++ syntax. +* [link N1962_vector_anchor \[N1962\] Vector]: Complete contracts for `std::vector` and a comparison with __N1962__ syntax. +* [link N1962_square_root_anchor \[N1962\] Square Root]: Comparison with D syntax. +* [link Mitchell02_counter_anchor \[Mitchell02\] Counter]: Subcontracting. +* [link Meyer97_stack4_anchor \[Meyer97\] Stack4]: Comparison with Eiffel syntax. +* [link Cline90_vector_anchor \[Cline90\] Vector]: Comparison with A++ syntax. -[heading \[N1962\] Vector: Comparison with C++ proposal's syntax] +[#N1962_vector_anchor] +[heading \[N1962\] Vector: STL Vector contracts and comparison with C++ contract proposal syntax] [import ../example/n1962/vector.cpp] [import ../example/n1962/vector_n1962.hpp] [table @@ -45,6 +46,7 @@ A few notable examples: [import ../example/n1962/sum.cpp] [n1962_sum] +[#N1962_square_root_anchor] [heading \[N1962\] Square Root: Default parameters and comparison with D syntax] [import ../example/n1962/sqrt.cpp] [import ../example/n1962/sqrt.d] @@ -53,6 +55,7 @@ A few notable examples: [ [[n1962_sqrt]] [[n1962_sqrt_d]] ] ] +[#Meyer97_stack4_anchor] [heading \[Meyer97\] Stack4: Comparison with Eiffel syntax] [import ../example/meyer97/stack4.hpp] [import ../example/meyer97/stack4_main.cpp] @@ -99,6 +102,7 @@ A few notable examples: [import ../example/mitchell02/observer_main.cpp] [mitchell02_observer_main] +[#Mitchell02_counter_anchor] [heading \[Mitchell02\] Counter: Subcontracting] [import ../example/mitchell02/counter/push_button.hpp] [mitchell02_push_button] @@ -109,6 +113,7 @@ A few notable examples: [import ../example/mitchell02/counter_main.cpp] [mitchell02_counter_main] +[#Cline90_vector_anchor] [heading \[Cline90\] Vector: Comparison with A++ proposed syntax] [import ../example/cline90/vector.hpp] [import ../example/cline90/vector_main.cpp] diff --git a/doc/getting_started.qbk b/doc/getting_started.qbk index 3ce59b3..28c6c3c 100644 --- a/doc/getting_started.qbk +++ b/doc/getting_started.qbk @@ -117,7 +117,7 @@ $ .\/introduction The above steps also work for Clang using =clang++= instead of =g++=. -Following a convention common to many Boost libraries, this library provides the [macroref BOOST_CONTACT_DYN_LINK] macro to be defined when compiling this library as a shared library instead. +Following a convention common to many Boost libraries, this library provides the [macroref BOOST_CONTRACT_DYN_LINK] macro to be defined when compiling this library as a shared library instead. If this macro is not defined, this library will be compiled as a statically linked library. There is also a [macroref BOOST_CONTRACT_HEADER_ONLY] macro that can be defined when compiling user programs instead of pre-compiling this library separately as either a static or shared library (because this library will then be composed only of header files so it no longer needs to be compiled separately). diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 1007735..c547785 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -182,7 +182,7 @@ The pointed old value is automatically qualified as `const` (so old values canno This library ensures that old value pointers are always not null by the time postconditions are checked (so programmers can safely dereference these pointers in postcondition assertions using `operator*` or `operator->` without having to check if old value pointers are not null first). Old values should never be used in preconditions (because old values are the same as the original values when preconditions are checked). -This library does not even guarantee that old value pointers are not null when precondition functors are called (for example, when postcondition contract checking is disabled using [macroref BOOST_CONTRACT_NO_POSTCONDITONS], when checking an overridden virtual public function contract via subcontracting, etc.). +This library does not even guarantee that old value pointers are not null when precondition functors are called (for example, when postcondition contract checking is disabled using [macroref BOOST_CONTRACT_NO_POSTCONDITIONS], when checking an overridden virtual public function contract via subcontracting, etc.). Finally, see __Old_Values_at_Body__ for delaying the assignment of old values until after preconditions (and possibly class invariants) are checked (this allows to program old value expressions under the simplifying assumption that precondition and class invariant assertions are satisfied already). The [macroref BOOST_CONTRACT_OLDOF] macro is actually a variadic macro and it takes an extra parameter when used in virtual or overriding public functions (see __Virtual_Public_Functions__ and __Overriding_Public_Functions__). @@ -558,7 +558,7 @@ It is the responsibility of the programmers to make sure that all bases passed t ] See __Access__ to avoid making `base_types` member type `public` (e.g., in cases when all public members of a class including `typedef`s must be controlled exactly). -Set the [macroref BOOST_CONTRACT_CONFIG_BASE_TYPES] configuration macro to use a name different from `base_types` (e.g., because `base_types` clashes with other names in the user-defined class). +Set the [macroref BOOST_CONTRACT_BASE_TYPEDEF] configuration macro to use a name different from `base_types` (e.g., because `base_types` clashes with other names in the user-defined class). [endsect] diff --git a/include/boost/contract.hpp b/include/boost/contract.hpp index ad0fc0b..52481b2 100644 --- a/include/boost/contract.hpp +++ b/include/boost/contract.hpp @@ -8,7 +8,21 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Include all header files required by this library at once. +Include all header files required by this library at once (for convenience). +All headers file boost/contract/\*.hpp are independent from one another +and can be included one-by-one to reduce the amount of the code of this library +being compiled in user code (but that should not make a significant difference). +Instead the headers boost/contract/core/\*.hpp are not independent from +other library headers and they are automatically included by the +boost/contract/\*.hpp headers (so the boost/contract/core/\*.hpp +headers are usually not directly included by programmers). + +All files under the boost/contract/detail/ directory, names within the +@c boost::contract::detail namespace, names prefixed with +@c boost_contract_detail... and @c BOOST_CONTRACT_DETAIL... (in any namesapce, +including user's code) are reserved for internal use of this library and should +never be used directly by programmers. +@see @RefSect{getting_started, Getting Started} */ #include diff --git a/include/boost/contract/assert.hpp b/include/boost/contract/assert.hpp index a8c66a5..ec9ef9c 100644 --- a/include/boost/contract/assert.hpp +++ b/include/boost/contract/assert.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Facilities to assert contract conditions. +Facility to assert contract conditions. */ #include @@ -27,17 +27,24 @@ Facilities to assert contract conditions. #else /** Preferred way to assert contract conditions. - Any exception thrown from within a preconditions, postcondition, and + Any exception thrown from within a preconditions, postcondition, or class invariant functor is interpreted by this library as a contract failure. Therefore, users can program contract assertions manually throwing - exceptions in case the asserted condition is checked to be @c false (this - library will then call the appropriate contract failure handler). - However, using this macro is preferred because in case @condition is + exceptions from the precondition, postcondition, or invariant functions when + the asserted condition is checked to be @c false (this library will then + call the appropriate contract failure handler + @RefFunc{boost::contract::precondition_failure}, etc.). + However, using this macro is preferred because in case @p condition is checked to be @c false, this macro expands to code that throws @RefClass{boost::contract::assertion_failure} with the correct assertion - file name (@c __FILE__), line number (@c __LINE__), and condition source - code text that will produce an informative error message. - @see @RefSect{advanced_topics, Advanced Topics}. + file name (__FILE__), line number (__LINE__), and asserted + condition source code so to produce an informative error message. + + This macro is not a variadic macro. Therefore, if @p condition contains + commas not already wrapped by round parenthesis, it needs to be wrapped by + an outer set of extra round parenthesis BOOST_CONTRACT_ASSERT((...)) + (as usual with C++ non-variadic macro parameters). + @see @RefSect{tutorial, Tutorial} @param condition The contract condition being checked. */ #define BOOST_CONTRACT_ASSERT(condition) /* nothing */ diff --git a/include/boost/contract/base_types.hpp b/include/boost/contract/base_types.hpp index a2cd3b7..ddcd9ef 100644 --- a/include/boost/contract/base_types.hpp +++ b/include/boost/contract/base_types.hpp @@ -10,7 +10,7 @@ // TODO: Document the max number of bases is 20 because of Boost.MPL vector limit. If Boost.MPL vector and related alg impl was to change to use variadic templates in the future there will be not limit to max bases (but for now this high limit is better than the extra complexity of reimpl all Boost.MPL vector, etc. within this lib with variadic templates). /** @file -Facilities to specify base classes so to support subcontracting. +Facility to specify inheritance form base classes (to support subcontracting). */ #include @@ -24,16 +24,21 @@ BOOST_CONTRACT_ERROR_macro_BASE_TYPES_requires_variadic_macros_otherwise_manuall #elif defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS) /** -Variadic macro to program base classes @c typedef. -A class that has contracts for one or more overriding public functions must -declare a @c typedef named @RefMacro{BOOST_CONTRACT_BASE_TYPEDEF} using this -macro. -This @c typedef can be programmed manually without this macro on compilers that -do not support variadic macros (see @RefSect{advanced_topics, Advanced Topics}). -@see @RefSect{tutorial, Tutorial}. -@param ... Comma separated list of base classes with must explicitly list their - access (@c public, @c protected, or @c private) and @c virtual (if - present) specifiers. +Used to program a @c typedef listing the bases of a derived class. +In order to support subcontracting, a derived class that specifies contracts for +one or more overriding public function must declare a @c typedef named +@RefMacro{BOOST_CONTRACT_BASE_TYPEDEF} using this macro. +This @c typedef must be @c public unless @RefClass{boost::contract::access} is +used. + +This is a variadic macro. On compilers that do not support variadic macros, the +base classes @c typedef can be programmed manually without using this macro (see +@RefSect{advanced_topics, Advanced Topics}). +@see @RefSect{tutorial, Tutorial} +@param ... Comma separated list of base classes. Each listed base must + explicitly list its access specifier @c public, @c protected, or + @c private, and @c virtual if present (this not always required in + C++ instead). */ #define BOOST_CONTRACT_BASE_TYPES(...) void /* dummy type for typedef */ diff --git a/include/boost/contract/call_if.hpp b/include/boost/contract/call_if.hpp index dabc012..0631305 100644 --- a/include/boost/contract/call_if.hpp +++ b/include/boost/contract/call_if.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Statically disable execution but also compilation of functor calls. +Statically disable compilation and execution of functor calls. */ // Do not include all_core_headers here (call_if is essentially standalone). @@ -40,16 +40,20 @@ Statically disable execution but also compilation of functor calls. namespace boost { namespace contract { /** -Unspecialized class template to control execution and compilation of functor -calls via a static boolean condition. -This class template has no member because it should never be used directly, it -should only be used via its specializations. +Class template to select compilation and execution of functor calls via a static +boolean condition. +This class template has no members because it is never used directly, it is only +used via its specializations. + +Usually this class template is instantiated only via the return value of +@RefFunc{boost::contract::call_if} and @RefFunc{boost::contract::call_if_c}. @see @RefSect{advanced_topics, Advanced Topics} -@tparam Cond Static boolean condition controlling functor calls. +@tparam Cond Static boolean condition selecting which functor call to compile + and execute. @tparam Then Type of functor to call when the static condition if true. -@tparam R Return type of then-branch functor. +@tparam ThenResult Return type of then-branch functor call. */ -templateresult_of should be evaluated only when the static - condition is already checked to be true (because @c Then() is - required to compile only in that case). Thus, this template - specialization introduces an extra level of indirectly necessary to the - proper lazy evaluation of that result-of. -The base class is a call-if statement so the else statement and other else-if -can be specified if needed. Ultimately this will return the return value of the -functor being compiled and called. +The base class is a call-if statement so the else and else-if statements can be +specified if needed. + +Usually this class template is instantiated only via the return value of +@RefFunc{boost::contract::call_if} and @RefFunc{boost::contract::call_if_c}. +@note The result_of::type expression should be evaluated only + when the static condition is already checked to be true (because + @c Then() is required to compile only in that case). This template + specialization introduces an extra level of indirection necessary for + the proper lazy evaluation of this result-of expression. @see @RefSect{advanced_topics, Advanced Topics} @tparam Then Type of functor to call when the static condition if true. */ @@ -90,10 +96,12 @@ struct call_if_statement(f) {} @@ -101,94 +109,92 @@ struct call_if_statement -struct call_if_statement { // Copyable (as *). +template +struct call_if_statement { // Copyable (as *). /** Construct this object with the then-branch functor. - @param f Then-branch nullary functor, called and compiled in this case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. + @param f Then-branch nullary templated functor. The functor call @c f() + is compiled and executed in this case (because the if-statement + static condition is true for this template specialization). The + return type of @c f() must be the same as (or implicitly + convertible to) the @p ThenResult type. */ - explicit call_if_statement(Then f) : r_(boost::make_shared(f())) {} + explicit call_if_statement(Then f) : + r_(boost::make_shared(f())) {} - /** Return value returned by the call to the then-branch functor. */ - operator R const&() const { return *r_; } - - /** Return value returned by the call to the then-branch functor. */ - operator R&() { return *r_; } + /** + This implicit type conversion returns a copy of the value returned by the + call to the then-branch functor. + */ + operator ThenResult() const { return *r_; } /** Specify the else-branch functor. - @param f Else-branch nullary functor, never called or compiled in this - case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. - @return Return value returned by the call to the then-branch functor. + @param f Else-branch nullary templated functor. The functor call @c f() + is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be the same as + (or implicitly convertible to) the @p ThenResult type. + @return A copy of the value returned by the call to the then-branch functor + (because the else-branch functor call is not executed in this case). */ template - R const& else_(Else const& f) const { return *r_; } + ThenResult else_(Else const& f) const { return *r_; } - /** - Specify the else-branch functor. - @param f Else-branch nullary functor, never called or compiled in this - case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. - @return Return value returned by the call to the then-branch functor. - */ - template - R& else_(Else const& f) { return *r_; } - /** Specify an else-if-branch functor. - @param f Else-if-branch nullary functor, never called or compiled in this - case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. - @tparam ElseIfCond Static boolean condition controlling functor calls. - @return The call-if statement so the else statement and other else-if can be - specified if needed. Ultimately will return the return value of the - then-branch functor in this case. + @param f Else-if-branch nullary templated functor. The functor call + @c f() is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be the same as + (or implicitly convertible to) the @p ThenResult type. + @tparam ElseIfCond Static boolean condition selecting which functor call to + compile and execute. + @return A call-if statement so the else statement and additional else-if + statements can be specified if needed. Ultimately it will return the + return value of the then-branch functor call in this case (because + the if-statement static condition is true for this template + specialization). */ template - call_if_statement else_if_c(ElseIfThen const& f) const { - return *this; - } + call_if_statement else_if_c(ElseIfThen const& f) + const { return *this; } /** Specify an else-if-branch functor. - @param f Else-if-branch nullary functor, never called or compiled in this - case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. - @tparam ElseIfCond Static boolean nullary meta-function controlling functor - calls. - @return The call-if statement so the else statement and other else-if can be - specified if needed. Ultimately will return the return value of the - then-branch functor in this case. + @param f Else-if-branch nullary templated functor. The functor call + @c f() is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be the same as + (or implicitly convertible to) the @p ThenResult type. + @tparam ElseIfCond Static boolean nullary meta-function selecting which + functor call to compile and execute. + @return A call-if statement so the else statement and additional else-if + statements can be specified if needed. Ultimately it will return the + return value of the then-branch functor call in this case (because + the if-statement static condition is true for this template + specialization). */ template - call_if_statement else_if(ElseIfThen const& f) const { - return *this; - } + call_if_statement else_if(ElseIfThen const& f) + const { return *this; } private: - boost::shared_ptr r_; + boost::shared_ptr r_; }; /** Template specialization to handle true static conditions for then-branch functor -calls returning void. +calls that return @c void. +Usually this class template is instantiated only via the return value of +@RefFunc{boost::contract::call_if} and @RefFunc{boost::contract::call_if_c}. @see @RefSect{advanced_topics, Advanced Topics} @tparam Then Type of functor to call when the static condition if true. */ @@ -196,37 +202,43 @@ template struct call_if_statement { // Copyable (no data). /** Construct this object with the then-branch functor. - @param f Then-branch nullary functor, called and compiled in this case. - The return type of this functor as well as of all other - specified functors for the call-if object must be @c void in - this case. + @param f Then-branch nullary templated functor. The functor call @c f() + is compiled and executed in this case (because the if-statement + static condition is true for this template specialization). The + return type of @c f() must be @c void in this case (because the + then-branch functor calls return @c void for this template + specialization). */ explicit call_if_statement(Then f) { f(); } - // Cannot provide `operator R()` here, because R is void. + // Cannot provide `operator ThenResult()` here, because ThenResult is void. /** Specify the else-branch functor. - @param f Else-branch nullary functor, never called or compiled in this - case. - The return type of this functor as well as of all other - specified functors for the call-if object must be @c void in - this case. + @param f Else-branch nullary templated functor. The functor call @c f() + is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be @c void in + this case (because the then-branch functor calls return @c void + for this template specialization). */ template void else_(Else const& f) const {} /** Specify an else-if-branch functor. - @param f Else-if-branch nullary functor, never called or compiled in this - case. - The return type of this functor as well as of all other - specified functors for the call-if object must be @c void in - this case. - @tparam ElseIfCond Static boolean condition controlling functor calls. - @return The call-if statement so the else statement and other else-if can be - specified if needed. Ultimately @c void will be returned in this - case. + @param f Else-if-branch nullary templated functor. The functor call + @c f() is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be @c void in + this case (because the then-branch functor calls return @c void + for this template specialization). + @tparam ElseIfCond Static boolean condition selecting which functor call to + compile and execute. + @return A call-if statement so the else statement and additional else-if + statements can be specified if needed. Ultimately it will return + @c void in this case (because the then-branch functor calls return + @c void for this template specialization). */ template call_if_statement else_if_c(ElseIfThen const& f) const { @@ -235,16 +247,18 @@ struct call_if_statement { // Copyable (no data). /** Specify an else-if-branch functor. - @param f Else-if-branch nullary functor, never called or compiled in this - case. - The return type of this functor as well as of all other - specified functors for the call-if object must be @c void in - this case. - @tparam ElseIfCond Static boolean nullary meta-function controlling functor - calls. - @return The call-if statement so the else statement and other else-if can be - specified if needed. Ultimately @c void will be returned in this - case. + @param f Else-if-branch nullary templated functor. The functor call + @c f() is never compiled and executed in this case (because the + if-statement static condition is true for this template + specialization). The return type of @c f() must be @c void in + this case (because the then-branch functor calls return @c void + for this template specialization). + @tparam ElseIfCond Static boolean nullary meta-function selecting which + functor call to compile and execute. + @return A call-if statement so the else statement and additional else-if + statements can be specified if needed. Ultimately it will return + @c void in this case (because the then-branch functor calls return + @c void for this template specialization). */ template call_if_statement else_if(ElseIfThen const& f) const { @@ -254,8 +268,11 @@ struct call_if_statement { // Copyable (no data). /** Template specialization to handle false static conditions. -This single specialization can handle both else-branch functor calls that -return void and that return non-void. +This one specialization handles all else-branch functor calls (whether they +return @c void or not). + +Usually this class template is instantiated only via the return value of +@RefFunc{boost::contract::call_if} and @RefFunc{boost::contract::call_if_c}. @see @RefSect{advanced_topics, Advanced Topics} @tparam Then Type of functor to call when the static condition if true. */ @@ -269,11 +286,12 @@ struct call_if_statement { /** Construct this object with the then-branch functor. - @param f Then-branch nullary functor, never called or compiled in this - case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. + @param f Then-branch nullary templated functor. The functor call @c f() + is never compiled and executed in this case (because the + if-statement static condition is false for this template + specialization). The return type of @c f() must be the same as + (or implicitly convertible to) the return type of the other + functor calls specified for this call-if object. */ explicit call_if_statement(Then const& f) {} @@ -281,15 +299,19 @@ struct call_if_statementresult_of should be evaluated only when the static - condition is already checked to be false (because @c Else() is - required to compile only in that case). Thus, that result-of is - evaluate lazily only in this template instantiation. - @param f Else-branch nullary functor, called and compiled in this case. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. - @return The return value of the call to the else-branch functor. + @note The result_of::type expression should be evaluated + only when the static condition is already checked to be false + (because @c Else() is required to compile only in that case). Thus, + this result-of expression is evaluated lazily only in + instantiations of this template. + @param f Else-branch nullary templated functor. The functor call @c f() + is compiled and executed in this case (because the if-statement + static condition is @c false for this template specialization). + The return type of @c f() must be the same as (or implicitly + convertible to) the return type of the other functor calls + specified for this call-if object. + @return A copy of the value returned by the call to the else-branch functor + @c f(). */ template #ifndef DOXYGEN @@ -301,15 +323,18 @@ struct call_if_statement call_if_statement else_if_c(ElseIfThen f) const { @@ -318,16 +343,18 @@ struct call_if_statement call_if_statement else_if(ElseIfThen f) @@ -337,15 +364,20 @@ struct call_if_statement @@ -354,15 +386,20 @@ call_if_statement call_if_c(Then f) { } /** -Make a call-if object with the specified then-branch functor -@param f Then-branch nullary functor, called and compiled if and only if - @c Cond::value if @c true. - The return type of this functor must be the same or implicitly - convertible into the return type of all other functors specified - for the call-if object. -@tparam Cond Static boolean nullary meta-function controlling functor calls. -@return The call-if statement so the else statement and other else-if can be - specified if needed. Ultimately will return the return value of the +Select compilation and execution of functor calls via a static boolean nullary +meta-function. +Make a call-if object with the specified then-branch functor. +@see @RefSect{advanced_topics, Advanced Topics} +@param f Then-branch nullary templated functor. The functor call @c f() is + compiled and executed if and only if @c Cond::value if @c true. The + return type of other functor calls specified for this call-if + statement (else-branches, else-if-branches, etc.) must be the same + as (or implicitly convertible to) the return type of then-branch + functor call @c f(). +@tparam Cond Static boolean nullary meta-function selecting which functor + call to compile and execute. +@return A call-if statement so else and else-if statements can be specified if + needed. Ultimately this will return the return value of the functor call being compiled and executed. */ template @@ -371,31 +408,39 @@ call_if_statement call_if(Then f) { } /** -Return value of specified functor call if and only if specified static condition -is true, otherwise return true. -@param f Nullary boolean functor to call and compile if and only if @c Cond - is @c true. -@tparam Cond Static boolean condition controlling functor compilation and call. -@return Boolean value returned by @c f() if static condition if true, otherwise - simply return @c true (i.e., check trivially passed). +Select compilation and execution of a boolean functor check via a static boolean +condition. +Compile and execute a boolean nullary functor call if and only if the specified +static condition is true, otherwise trivially return @c true. +@see @RefSect{advanced_topics, Advanced Topics} +@param f Boolean nullary templated functor. The functor call @c f() is + compiled and executed if and only if @c Cond is @c true. +@tparam Cond Static boolean condition selecting when the functor call should + be compiled and executed. +@return Boolean value returned by @c f() if the static condition if true, + otherwise simply return @c true (i.e., check trivially passed). */ -template -bool check_if_c(F f) { +template +bool check_if_c(Check f) { return call_if_c(f).else_( boost::contract::detail::always_true()); } /** -Return value of specified functor call if and only if specified static condition -is true, otherwise return true. -@param f Nullary boolean functor to call and compile if and only if - @c Cond::value is @c true. -@tparam Cond Static boolean nullary meta-function controlling functor calls. -@return Boolean value returned by @c f() if static condition if true, otherwise - simply return @c true (i.e., check trivially passed). +Select compilation and execution of a boolean functor check via a static boolean +nullary meta-function. +Compile and execute a boolean nullary functor call if and only if the specified +static condition is true, otherwise trivially return @c true. +@see @RefSect{advanced_topics, Advanced Topics} +@param f Boolean nullary templated functor. The functor call @c f() is + compiled and executed if and only if @c Cond::value is @c true. +@tparam Cond Static boolean nullary meta-function selecting when the functor + call should be compiled and executed. +@return Boolean value returned by @c f() if the static condition if true, + otherwise simply return @c true (i.e., check trivially passed). */ -template -bool check_if(F f) { +template +bool check_if(Check f) { return call_if_c(f).else_( boost::contract::detail::always_true()); } diff --git a/include/boost/contract/constructor.hpp b/include/boost/contract/constructor.hpp index f727879..b03cd33 100644 --- a/include/boost/contract/constructor.hpp +++ b/include/boost/contract/constructor.hpp @@ -24,57 +24,68 @@ namespace boost { namespace contract { /** Program contracts for constructors. -This is used to specify postconditions and check class invariants for -constructors (see @RefClass{boost::contract::constructor_precondition} to -specify preconditions for constructors instead). -@see @RefSect{tutorial, Tutorial}. -@param obj The object @c this in scope of the constructor being contracted. -@return The result of this function must be assigned to variable of type - @RefClass{boost::contract::guard} declared locally within the - constructor being contracted. +This is used to specify postconditions, old value assignments at body, and +check class invariants for constructors (see +@RefClass{boost::contract::constructor_precondition} to specify preconditions +for constructors instead). + +For optimization, this can be omitted for constructors that do not have +postconditions when the enclosing class has no invariants. +@see @RefSect{tutorial, Tutorial} +@param obj The object @c this from the scope of the contracted constructor. +@return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the body + of the contracted constructor (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ -template -set_old_postcondition<> constructor(C* obj) { - // Must #if also on ..._PRECONDITIONS here because set_... is generic. +template +specify_old_postcondition<> constructor(Class* obj) { + // Must #if also on ..._PRECONDITIONS here because specify_... is generic. #if !defined(BOOST_CONTRACT_NO_CONSTRUCTORS) || \ !defined(BOOST_CONTRACT_NO_PRECONDITIONS) - return set_old_postcondition<>( - new boost::contract::detail::constructor(obj)); + return specify_old_postcondition<>( + new boost::contract::detail::constructor(obj)); #else - return set_old_postcondition<>(); + return specify_old_postcondition<>(); #endif } // TODO: Document that constructor_precondition for unions must be called at the very beginning of ctor body before `boost::contract::guard c = ...` (because unions cannot have base classes, not even in C++11). /** -Program constructor preconditions. -This class must be the very first base class of the class being contracted. Also -the contracted class must privately inherit from this base class. +Program preconditions for constructors. +This class must be the very first base class of the contracted class. Also the +contracted class shall privately inherit from this base class (to not alter the +contracted class public interface). -Unions cannot have base classes so this class can be used to declare a local -object within the constructor function just before -@RefClass{boost::contract::constructor} is used (see +Unions cannot have base classes in C++ so this class can be used to declare a +local object within the constructor function just before +@RefFunc{boost::contract::constructor} is used (see @RefSect{advanced_topics, Advanced Topics}). -@see @RefSect{tutorial, Tutorial}. -@tparam C Class of constructor being contracted (CRTP used here to avoid - multiple instances of same base class error). +@see @RefSect{tutorial, Tutorial} +@tparam Class Class of contracted constructor. */ -template -class constructor_precondition { // Copyable (no data). +template +class constructor_precondition { // Copyable (has no data). public: - /** Construct this object for constructor that do not have preconditions. */ + /** + Construct this object without specifying constructor preconditions. + This is implicitly called for those constructors of the contracted class + that do not specify preconditions. + */ constructor_precondition() {} /** - Constructor this object specifying constructor preconditions. - @param f Functor called by this library to check preconditions. Any - exception thrown by a call to this functor indicates a - precondition failure. Assertions within this functor are usually - programmed using @RefMacro{BOOST_CONTRACT_ASSERT}. This functor - must be a nullary functor. This functor could capture variables - by value, or better by (constant) reference to void extra - copies. + Construct this object specifying constructor preconditions. + @param f Functor called by this library to check constructor + preconditions @c f(). Precondition assertions within this + functor call are usually programmed using + @RefMacro{BOOST_CONTRACT_ASSERT}, but any exception thrown by a + call to this functor indicates a precondition failure (and will + result in this library calling + @RefFunc{boost::contract::precondition_failure}). This functor + must be a nullary functor. This functor can capture variables by + value, or better by (constant) reference to avoid extra copies. */ template explicit constructor_precondition(F const& f) { diff --git a/include/boost/contract/core/access.hpp b/include/boost/contract/core/access.hpp index a158b65..c08e927 100644 --- a/include/boost/contract/core/access.hpp +++ b/include/boost/contract/core/access.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Used to declare invariants, base types, etc private members. +Facility to declare invariants, base types, etc all as private members. */ #include @@ -23,6 +23,7 @@ Used to declare invariants, base types, etc private members. #include #include #endif +#include // TODO: Review all warnings for examples, tests, and also lib compilation... @@ -45,18 +46,27 @@ namespace boost { namespace boost { namespace contract { /** -Friend class to declare invariants, base types, etc private members. -Declare this class as friend of the class being contracted in order to declare -the class invariants member functions and the base types as non-public members. -@note Not making this class friend will cause compiler errors on some compilers -(e.g., MSVC) because the private members needed for contracts will not be -accessible. On other compilers (e.g., GCC and CLang), the private access will -instead fail SFINAE and no compiler error will be reported but invariants and -subcontracting will be silently be skipped at run-time. Therefore programmers -must make sure to either declare contract members public or to make this class -a friend. +Friend this class to declare invariants and base types as private members. +Declare this class as friend of the contracted class in order to declare +the invariants functions and the base types @c typedef as non-public members. +In real code, programmers will likely chose to declare this class as friend so +to fully control the contracted class public interface. + +This class is not intended to be directly used by programmers a part from +declaring it @c friend (and that is why this class does not have any public +member and it is not copyable). + +@note Not making this class friend of the contracted class will cause + compiler errors on some compilers (e.g., MSVC) because the private + members needed to check the contracts will not be accessible. On other + compilers (e.g., GCC and CLang), the private access will instead fail + SFINAE and no compiler error will be reported while invariants and + subcontracting will be silently skipped at run-time. Therefore, + programmers must make sure to either declare invariant functions and + base types @c typedef as public members or to make this class a friend. +@see @RefSect{advanced_topics, Advanced Topics} */ -class access { // Copyable (as shell with no data member). +class access : private boost::noncopyable { /** @cond */ // No public APIs (so users cannot use it directly by mistake). diff --git a/include/boost/contract/core/config.hpp b/include/boost/contract/core/config.hpp index 9302f9e..4fd5009 100644 --- a/include/boost/contract/core/config.hpp +++ b/include/boost/contract/core/config.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Configuration macros. +Facilities to configure this library compile-time and run-time behaviour. */ // IMPORTANT: This header MUST NOT #include any other header of this lib. @@ -22,32 +22,37 @@ Configuration macros. /** Define this macro to compile this library as a shared library or DLL (undefined by default). - In general, this library must be compiled as a shared library defining this - macro when used by multiple programs otherwise the contracts will not - necessarily be checked correctly at run-time. - Rationale: Named after @c BOOST_ALL_DYN_LINK. - @see @RefSect{getting_started, Getting Started}. + In general, this library must be compiled as a shared library (a.k.a., + Dynamically Linked Library (DLL)) by defining this macro. That is necessary + when the same library instance is used by multiple programs (otherwise the + contracts will not necessarily be checked correctly at run-time). + + @b Rationale: Named after @c BOOST_ALL_DYN_LINK. + @see @RefSect{getting_started, Getting Started} */ #define BOOST_CONTRACT_DYN_LINK #endif #ifdef DOXYGEN /** - Define this macro to compile user code with this library composed of headers - only (undefined by default). + Define this macro when compiling user code to avoid compiling this library + (undefined by default). If this macro is defined, this library does not have to be compiled - separately. This library headers can simply be included in the user program - and this library code will be compiled directly as part of the user program. - However, in general this library must be compiled as a shared library - defining @RefMacro{BOOST_CONTRACT_DYN_LINK} when used by multiple programs - otherwise the contracts will not necessarily be checked correctly at - run-time. - Rationale: Named after @c BOOST_CHRONO_HEADER_ONLY. - @see @RefSect{getting_started, Getting Started}. + separately from user code. This library headers are simply included in the + user program and this library implementation code is compiled as part of the + user program. However, in general this library must be compiled as a shared + library defining @RefMacro{BOOST_CONTRACT_DYN_LINK} when it is used by + multiple programs (otherwise the contracts will not necessarily be checked + correctly at run-time). + + @b Rationale: Named after @c BOOST_CHRONO_HEADER_ONLY. + @see @RefSect{getting_started, Getting Started} */ #define BOOST_CONTRACT_HEADER_ONLY #endif +// TODO: Document that no code should in general be programmed before the contract in function definitions, but for example mutex locks can be programmed before contracts if necessary for synchronization. + #ifdef DOXYGEN /** Define this macro to not lock internal library data for thread safety @@ -55,13 +60,13 @@ Configuration macros. Defining this macro will make the library implementation code not thread safe so this macro should not be defined unless the library is being used strictly under single-threaded applications. However, when this macro is - left undefined this library needs to use "global" locks to ensure contract + left undefined this library needs to use "global" locks (to ensure contract checking is globally disabled when other contracts are being checked and - also to safely access the failure handler functors (this could introduce a - significant amount of synchronization in multi-threaded applications). - Rationale: Named after @c BOOST_DISABLE_THREADS, - @c BOOST_ASIO_DISABLE_THREADS, etc. - @see @RefSect{contract_programming_overview, Contract Programming Overview}. + also to safely access the failure handler functors) and that could introduce + a significant amount of synchronization in some multi-threaded applications. + + @b Rationale: Named after @c BOOST_DISABLE_THREADS. + @see @RefSect{contract_programming_overview, Contract Programming Overview} */ #define BOOST_CONTRACT_DISABLE_THREADS #endif @@ -70,17 +75,19 @@ Configuration macros. /** Maximum number of function arguments when no variadic macros are supported (default to @c 10). - This defines the maximum number of arguments of the overriding public - function pointer passed to @RefFunc{boost::contract::public_function} on - compilers that do not support variadic macros. This macro has no effect on - compilers that support variadic macros. + On compilers that support variadic macros, this macro has no effect. + On compilers that do not support variadic macros, this macro can be defined + to support a maximum number of arguments different than @c 10 for + overriding public functions (contracted via + @RefFunc{boost::contract::public_function}). @note Regardless of the value of this macro and of compiler support for variadic macros, there is an intrinsic limit around 19 arguments - for overriding public functions (because of a similar limit of some + for overriding public functions (because of similar limits for some Boost libraries like Boost.MPL and Boost.FunctionTypes internally used by this library). - Rationale: Named after @c BOOST_FUNCTION_MAX_ARGS, etc. + @b Rationale: Named after @c BOOST_FUNCTION_MAX_ARGS. + @see @RefSect{tutorial, Tutorial} */ #define BOOST_CONTRACT_MAX_ARGS 10 #endif @@ -88,102 +95,122 @@ Configuration macros. #ifndef BOOST_CONTRACT_BASE_TYPEDEF /** Define the name of the base type @c typedef (@c base_types by default). - Rationale: This cannot be called @c BOOST_CONTRACT_BASE_TYPES - because that is already used as the name of macro to - extract the public bases. Then - @c BOOST_CONTRACT_BASE_TYPEDEF is a reasonable naming - alternative (but without changing this macro default to - @c base_typedef because - typedef BOOST_CONTRACT_BASE_TYPES(...) base_types - is the preferred syntax in user code). + This macro can be defined if the @c typedef declared using + @RefMacro{BOOST_CONTRACT_BASE_TYPES} must have a name different than + @c base_types. + + @b Rationale: This macro cannot be called @c BOOST_CONTRACT_BASE_TYPES + because that is already the name of the macro that extracts + public bases. Then @c BOOST_CONTRACT_BASE_TYPEDEF is a + reasonable name (but without changing this macro default + definition to @c base_typedef because @c base_types is + remains the preferred syntax for user code). + @see @RefSect{tutorial, Tutorial} */ #define BOOST_CONTRACT_BASE_TYPEDEF base_types #endif #ifndef BOOST_CONTRACT_INVARIANT /** - Define the name of the @c const and const volatile member functions - that checks mutable and volatile class invariants respectively (@c invariant - by default). + Define the name of the invariant member functions (@c invariant by defult). + This macro expands to the name of the @c const and const volatile + member functions that check mutable and volatile class invariants + respectively. This macro can be defined if the invariant functions need to + be named differently from @c invariant. + @see @RefSect{tutorial, Tutorial} */ #define BOOST_CONTRACT_INVARIANT invariant #endif #ifndef BOOST_CONTRACT_STATIC_INVARIANT /** - Define the name of the @c static member function that checks static class - invariants (@c static_invariant by default). - @note C++ does not allow to overload member functions based on static - classifier, so a name different from the non-static class invariant - name expanded by @RefMacro{BOOST_CONTRACT_INVARIANT} must be used - here. + Define the name of the static invariant member function (@c static_invariant + by defult). + This macro expands to the name of the @c static member function that checks + static class invariants. This macro can be defined if the static invariant + function needs to be named differently from @c static_invariant. + + @b Rationale: C++ does not allow to overload member functions based on the + @c static classifier, so a name different from the one + expanded by @RefMacro{BOOST_CONTRACT_INVARIANT} needed to be + used here. + @see @RefSect{tutorial, Tutorial} */ #define BOOST_CONTRACT_STATIC_INVARIANT static_invariant #endif #ifdef DOXYGEN /** - Disable a number of static checks and compiler warnings generated by this - library (undefined by default). - Among other things, this macro checks: - @li Static invariant member function is @c static. - @li Non-static invariant member function is either @c const, + Disable a number of static checks and related compile-time errors generated + by this library (undefined by default). + Among other compile-time errors, defining this macro disables compile-time + error for the following checks: + @li The static invariant member function must be @c static. + @li Non-static invariant member functions must be either @c const, const volatile, or volatile const. - @li A class that has contracts for one or more overriding public functions - must also define the @RefMacro{BOOST_CONTRACT_BASE_TYPES} @c typedef. + @li A class that programs contracts for one or more overriding public + functions via @RefFunc{boost::contract::public_function} must also + define the @RefMacro{BOOST_CONTRACT_BASE_TYPES} @c typedef. */ #define BOOST_CONTRACT_PERMISSIVE #endif #ifdef DOXYGEN /** - Code block to execute if boost::contract::guard c = ... assignment is - missing (undefined by default). - In general, if programmer omit this assignment, it is a logic error in the - program. Therefore, when this macro is not defined, by default this library - calls calls @c assert with a @c false condition. If this macro is defined, - this library will execute the code expanded by this macro instead of calling - @c assert. + Code block to execute if contracts are not assigned to a + @RefClass{boost::contract::guard} variable (undefined by default). + In general, there is a logic error in the program when contracts are not + assigned to a local variable of type @RefClass{boost::contract::guard}. + Therefore, by default (i.e., when this macro is not defined) this library + calls @c assert with a @c false condition in such cases. If this macro is + defined, this library will execute the code expanded by the macro instead of + calling @c assert (if programmers prefer to throw an exception, etc.). */ - #define OOST_CONTRACT_ON_MISSING_GUARD + #define BOOST_CONTRACT_ON_MISSING_GUARD #endif #ifdef DOXYGEN /** - If defined, checking preconditions does not disable checking of other - assertions (undefined by default). - This is what [N1962] does by default because unchecked arguments are passed - to function bodies if contract checking is disable within precondition - checking (function bodies need to be executed directly or indirectly while - checking the preconditions in question). However, not disabling assertion - checking while checking preconditions can lead to infinite recursive calls - in user code so by default this macro is not defined. + Define this macro to not disable other any assertion checking while checking + preconditions (undefined by default). + The @RefSect{bibliography, [N1962]} proposal does not disable any assertion + checking while checking preconditions (because unchecked arguments can be + passed to function bodies if contract checking is disabled within + precondition checking when function bodies are executed directly or + indirectly to check the preconditions in question). However, not disabling + assertion checking while checking preconditions can lead to infinite + recursion in user code so by default this macro is not defined (but this + macro can be defined to obtain the behaviour specified in + @RefSect{bibliography, [1962]}). + @see @RefSect{contract_programming_overview, Contract Programming Overview} */ - #define OOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION + #define BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION #endif #ifdef DOXYGEN /** If defined, this library does not check preconditions at run-time (undefined by default). - This library implementation code is also optimized to avoid overhead in - associated with precondition checking when possible also at compile-time. - Users can manually program @c #ifdef statements using this macro to disable - precondition compilation (not just run-time checking). - @see @RefSect{advanced_topics, Advanced Topics}. + If this macro is defined, this library implementation code is also optimized + to reduce compile-time (not just run-time) overhead associated with checking + preconditions. Users can also manually program @c \#ifdef statements in + their code using this macro to completely disable compilation of + preconditions (not recommended). + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_PRECONDITIONS #endif #ifdef DOXYGEN /** - If defined, this library does not check postconditions at run-time - (undefined by default). - This library implementation code is also optimized to avoid overhead in - associated with postcondition checking when possible also at compile-time. - Users can manually program @c #ifdef statements using this macro to disable - postcondition compilation (not just run-time checking). - @see @RefSect{advanced_topics, Advanced Topics}. + If defined, this library does not check postconditions and does not copy old + values at run-time (undefined by default). + If this macro is defined, this library implementation code is also optimized + to reduce compile-time (not just run-time) overhead associated with checking + postconditions and copying old values. Users can also manually program + @c \#ifdef statements in their code using this macro to completely disable + compilation of postconditions and old values (not recommended). + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_POSTCONDITIONS #endif @@ -193,15 +220,13 @@ Configuration macros. /** If defined, this library does not check entry invariants at run-time (undefined by default). - This library implementation code is also optimized to avoid overhead in - associated with entry invariant checking when possible also at compile-time. - Users can manually program @c #ifdef statements using this macro to disable - class invariant compilation (not just run-time checking). - + If this macro is defined, this library implementation code is also optimized + to reduce compile-time (not just run-time) overhead associated with + checking class invariants at function entry. + This macro can always be defined by itself but it is also automatically defined when @RefMacro{BOOST_CONTRACT_NO_INVARIANTS} is defined. - - @see @RefSect{advanced_topics, Advanced Topics}. + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_ENTRY_INVARIANTS #endif @@ -209,17 +234,15 @@ Configuration macros. #if defined(DOXYGEN) || (!defined(BOOST_CONTRACT_NO_EXIT_INVARIANTS) && \ defined(BOOST_CONTRACT_NO_INVARIANTS)) /** - If defined, this library does not check exit invariant at run-time + If defined, this library does not check exit invariants at run-time (undefined by default). - This library implementation code is also optimized to avoid overhead in - associated with exit invariant checking when possible also at compile-time. - Users can manually program @c #ifdef statements using this macro to disable - class invariant compilation (not just run-time checking). - + If this macro is defined, this library implementation code is also optimized + to reduce compile-time (not just run-time) overhead associated with + checking class invariants at function exit. + This macro can always be defined by itself but it is also automatically defined when @RefMacro{BOOST_CONTRACT_NO_INVARIANTS} is defined. - - @see @RefSect{advanced_topics, Advanced Topics}. + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_EXIT_INVARIANTS #endif @@ -230,16 +253,16 @@ Configuration macros. /** If defined, this library does not check class invariants at run-time (undefined by default). - This library implementation code is also optimized to avoid overhead in - associated with class invariant checking when possible also at compile-time. - Users can manually program @c #ifdef statements using this macro to disable - class invariant compilation (not just run-time checking). - + If this macro is defined, this library implementation code is also optimized + to reduce compile-time (not just run-time) overhead associated with + checking class invariants (at both function entry and exit). Users can also + manually program @c \#ifdef statements in their code using this macro to + completely disable compilation of class invariants (not recommended). + This macro can always be defined by itself but it is also automatically defined when @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS} and @RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS} are both defined. - - @see @RefSect{advanced_topics, Advanced Topics}. + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_INVARIANTS #endif @@ -252,19 +275,22 @@ Configuration macros. #elif defined(BOOST_CONTRACT_NO_POSTCONDITIONS) && \ defined(BOOST_CONTRACT_NO_INVARIANTS) /** - This library defines this macro if constructor contracts are not being - checked by @RefFunc{boost::contract::constructor}. - This macro is automatically defined or not by this library, and it is not a + Defined by this library if constructor contracts are not being checked by + @RefFunc{boost::contract::constructor}. + Users can manually program @c \#ifdef statements in their code using this + macro to completely disable compilation of constructor contracts (not + recommended). + + This macro is automatically defined by this library, and it is not a configuration macro. This library will generate a compile-time error if - users manually define this macro. - Users can manually define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, + programmers try to manually define this macro. Programmers can manually + define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, @RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and - @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead. - - Note that constructor preconditions are checked separately by - @RefClass{boost::contract::constructor_precondition} so their run-time check - ing is disabled by @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS} directly. - @see @RefSect{advanced_topics, Advanced Topics}. + @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead (constructor + preconditions are checked separately by + @RefClass{boost::contract::constructor_precondition} so they are disabled by + @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS}). + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_CONSTRUCTORS #endif @@ -274,16 +300,21 @@ Configuration macros. #elif defined(BOOST_CONTRACT_NO_POSTCONDITIONS) && \ defined(BOOST_CONTRACT_NO_INVARIANTS) /** - This library defines this macro if destructor contracts are not being - checked by @RefFunc{boost::contract::destructor}. - This macro is automatically defined or not by this library, and it is not a + Defined by this library if destructor contracts are not being checked by + @RefFunc{boost::contract::destructor}. + Users can manually program @c \#ifdef statements in their code using this + macro to completely disable compilation of destructor contracts (not + recommended). + + This macro is automatically defined by this library, and it is not a configuration macro. This library will generate a compile-time error if - users manually define this macro. - Users can manually define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, + programmers try to manually define this macro. Programmers can manually + define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, @RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and - @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead. - (Note that destructors have no preconditions.) - @see @RefSect{advanced_topics, Advanced Topics}. + @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead (destructors have no + preconditions, see also @RefSect{contract_programming_overview, Contract + Programming Overivew}). + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_DESTRUCTORS #endif @@ -294,16 +325,20 @@ Configuration macros. defined(BOOST_CONTRACT_NO_POSTCONDITIONS) && \ defined(BOOST_CONTRACT_NO_INVARIANTS) /** - This library defines this macro if public function contracts are not being - checked by @RefFunc{boost::contract::public_function}. - This macro is automatically defined or not by this library, and it is not a + Defined by this library if public function contracts are not being checked + by @RefFunc{boost::contract::public_function}. + Users can manually program @c \#ifdef statements in their code using this + macro to completely disable compilation of public function contracts (not + recommended). + + This macro is automatically defined by this library, and it is not a configuration macro. This library will generate a compile-time error if - users manually define this macro. - Users can manually define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, + programmers try to manually define this macro. Programmers can manually + define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS}, @RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead. - @see @RefSect{advanced_topics, Advanced Topics}. + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS #endif @@ -313,15 +348,20 @@ Configuration macros. #elif defined(BOOST_CONTRACT_NO_PRECONDITIONS) && \ defined(BOOST_CONTRACT_NO_POSTCONDITIONS) /** - This library defines this macro if non-member, private, or protected - function contracts are not being checked by - @RefFunc{boost::contract::function}. - This macro is automatically defined or not by this library, and it is not a + Defined by this library if non-member, private, and protected function + contracts are not being checked by @RefFunc{boost::contract::function}. + Users can manually program @c \#ifdef statements in their code using this + macro to completely disable compilation of non-member, private, and + protected function contracts (not recommended). + + This macro is automatically defined by this library, and it is not a configuration macro. This library will generate a compile-time error if - users manually define this macro. - Users can manually define @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS} and - @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead. - @see @RefSect{advanced_topics, Advanced Topics}. + programmers try to manually define this macro. Programmers can manually + define @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS} and + @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead (private and protected + functions do not check class invariants, see also + @RefSect{contract_programming_overview, Contract Programming Overview}). + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_FUNCTIONS #endif @@ -333,16 +373,20 @@ Configuration macros. defined(BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS) && \ defined(BOOST_CONTRACT_NO_FUNCTIONS) /** - This library defines this macro if no contracts (for any operation) are - being checked. - This macro is automatically defined or not by this library, and it is not a + Defined by this library if no contracts (for any operation) are being + checked. + Users can manually program @c \#ifdef statements in their code using this + macro to completely disable inclusion of this library headers, etc. (not + recommended). + + This macro is automatically defined by this library, and it is not a configuration macro. This library will generate a compile-time error if - users manually define this macro. - Users can manually define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, + programmers try to manually define this macro. Programmers can manually + define @RefMacro{BOOST_CONTRACT_NO_ENTRY_INVARIANTS}, @RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS}, @RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead. - @see @RefSect{advanced_topics, Advanced Topics}. + @see @RefSect{advanced_topics, Advanced Topics} */ #define BOOST_CONTRACT_NO_ALL #endif diff --git a/include/boost/contract/core/exception.hpp b/include/boost/contract/core/exception.hpp index 4f98f71..bee3228 100644 --- a/include/boost/contract/core/exception.hpp +++ b/include/boost/contract/core/exception.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Exception and utilities to report contract assertion failures. +Exceptions and other facilities to handle contract assertion failures. */ #include @@ -23,50 +23,68 @@ Exception and utilities to report contract assertion failures. // because user code might explicitly call precondition_failure() (for whatever // reason...). Otherwise, the public API of this lib will change. +#ifdef DOXYGEN +// Needed for `std::` prefix to show (but remove via `EXCLUDE_SYMBOLS=std`). +namespace std { + class exception {}; + class bad_cast {}; +} +#endif + namespace boost { namespace contract { /** Public base class for all this library exceptions. This class does not inherit from @c std::exception because derived exceptions -will (inheriting from @c std::exception, or @c std::bad_cast, etc.). -@see @RefSect{advanced_topics, Advanced Topics}. +will (inheriting from @c std::exception, @c std::bad_cast, etc.). +@see @RefSect{advanced_topics, Advanced Topics} */ class BOOST_CONTRACT_DETAIL_DECLSPEC exception { public: - /** Destruct this object. */ - virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW; + /** + Destruct this object. + @b Throws: @c noexcept (or @c throw() if no C++11). + */ + virtual ~exception() /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; }; /** -Exception internally thrown by for inconsistent return values passed to -overridden virtual public functions. -This exception is internally thrown by this library when users specify a return -value for an overriding public function in a derived class that is inconsistent -with the return type of the virtual public function being overridden in the base -class. +Exception thrown when inconsistent return values are passed to overridden +virtual public functions. +This exception is internally thrown by this library when programmers specify +return values for overriding public functions in derived classes that are +inconsistent with the return types of the virtual public functions being +overridden from base classes. -Rationale: The @c boost::bad_any_cast exception could not be used - because it does not print the from and to type names (so it - is not descriptive enough). - -@see @RefSect{tutorial, Tutorial}. +@b Rationale: The @c boost::bad_any_cast exception could not be used because + it does not print the from- and to- type names (so it is not + descriptive enough). +@see @RefSect{tutorial, Tutorial} */ class BOOST_CONTRACT_DETAIL_DECLSPEC bad_virtual_result_cast : // Copy (as str). public std::bad_cast, public boost::contract::exception { public: /** - Construct this object with the name of the from and to types. - @param from_type_name Name of the source type. - @param to_type_name Name of the type destination type. + Construct this object with the name of the from- and to- types. + @param from_type_name Name of the from-type (source). + @param to_type_name Name of the to-type (destination). */ explicit bad_virtual_result_cast(char const* from_type_name, char const* to_type_name); - /** Destruct this object. */ - virtual ~bad_virtual_result_cast() BOOST_NOEXCEPT_OR_NOTHROW; + /** + Destruct this object. + @b Throws: @c noexcept (or @c throw() if no C++11). + */ + virtual ~bad_virtual_result_cast() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; - /** Return an error description (containing both from and to type names). */ - virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW; + /** + Description for this error (containing both from- and to- type names). + @b Throws: @c noexcept (or @c throw() if no C++11). + */ + virtual char const* what() const + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** @cond */ private: @@ -78,64 +96,77 @@ private: Exception typically used to report a contract assertion failure. This exception is thrown by code expanded by @RefMacro{BOOST_CONTRACT_ASSERT} (but it can also be thrown by user code programmed manually without that macro). -@see @RefSect{advanced_topics, Advanced Topics}. +This exception is typically used to report contract assertion failures because +it contains detailed information about the assertion file name, line number, +condition source code, etc. (so it provides detailed error messages), but any +other exception can be used to report a contract assertion failure. This library +will call the appropriate contract failure handler function +(@RefFunc{boost::contract::precondition_failure}, etc.) when this or any other +exception is thrown while checking contracts (by default, these failure handler +functions terminate the program but they can be customized to take any other +action). +@see @RefSect{advanced_topics, Advanced Topics} */ class BOOST_CONTRACT_DETAIL_DECLSPEC assertion_failure : // Copy (as str, etc.). public std::exception, public boost::contract::exception { public: /** - Construct this object optionally with assertion file, line, and code - information. - This constructor can also be used to specify no information, or to specify - only file and line but not code information (because of its parameter - default values). + Construct this object with the asserted condition file name, line number, + and source code text (all optional). + This constructor can also be used to specify no information (default + constructor), or to specify only file name and line number but not source + code text (because of its parameter default values). @param file Name of the file containing the assertion (usually set using __FILE__). @param line Number of the line containing the assertion (usually set using __LINE__). - @param code String text of the condition code being asserted. + @param code Text listing the source code of the asserted condition. */ explicit assertion_failure(char const* const file = "", unsigned long const line = 0, char const* const code = ""); /** - Construct this object with code information. - This constructor can be used to specify only code but no file and line - information. - @param code String text of the condition code being asserted. + Construct this object with the asserted condition source code text only. + @param code Text listing the source code of the asserted condition. */ explicit assertion_failure(char const* const code); - /** Destruct this object. */ - virtual ~assertion_failure() BOOST_NOEXCEPT_OR_NOTHROW; - /** - Return string describing the failed assertion. - @return Return a string similar to - assertion "`code()`" failed: file "`file()`", line \`line()\` - (parts of this information will be omitted if they were not - specified at construction). + Destruct this object. + @b Throws: @c noexcept (or @c throw() if no C++11). */ - virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW; + virtual ~assertion_failure() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** - Return assertion file. - @return Return file as specified at construction (or @c "" if no file was + String describing the failed assertion. + @b Throws: @c noexcept (or @c throw() if no C++11). + @return A string formatted similarly to the following: + assertion "`code()`" failed: file "`file()`", line \`line()\`. + File, line, and code will be omitted from this string if they were + not specified at construction. + */ + virtual char const* what() const + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; + + /** + Name of the file listing the assertion. + @return File as specified at construction (or @c "" if no file was specified). */ char const* const file() const; /** - Return assertion line number. - @return Return line number as specified at construction (or @c 0 if no line - number was specified). + Number of the line listing the assertion. + @return Line number as specified at construction (or @c 0 if no line number + was specified). */ unsigned long line() const; /** - Return assertion condition code. - @return Return assertion condition code as specified at construction (or - @c "" if no code was specified at construction). + Text listing the source code of the asserted condition. + @return Asserted condition source code as specified at construction (or + @c "" if no code was specified). */ char const* const code() const; @@ -151,159 +182,236 @@ private: }; /** -Context of assertion failure. -This is passed as a parameter of the assertion failure handler functions. -For example, it might be necessary to know the kind of operation that threw an -assertion failure to make sure exception are never thrown by destructors even -when contract failures are handled by throwing exceptions instead of terminating -the program (default). -@see @RefSect{advanced_topics, Advanced Topics}. +Represent the operation where the contract assertion failed. +This is passed as a parameter to the assertion failure handler functions. +For example, it might be necessary to know in which operation an assertion +failed to make sure exceptions are never thrown from destructors, not even +when contract failure handlers are reprogrammed by users to throw exceptions +instead of terminating the program. +do). +@see @RefSect{advanced_topics, Advanced Topics} */ enum from { - /** Assertion failed in constructor contract. */ + /** Assertion failed when checking constructor contracts. */ from_constructor, - /** Assertion failed in destructor contract. */ + /** Assertion failed when checking destructor contracts. */ from_destructor, - /** Assertion failed in function (member or not) contract. */ + /** Assertion failed when checking function (member or not) contracts. */ from_function }; /** -Typef all assertion failure handler functions. -Rationale: Using Boost.Function to handle also lambdas, binds, etc. -@see @RefSect{advanced_topics, Advanced Topics}. +Type of all assertion failure handler functions. +As specified by this type, assertion failure handler functions must be functors +returning @c void and taking a single parameter of type +@RefEnum{boost::contract::from}. + +@b Rationale: Using Boost.Function allows to handle any functor (functions but +also lambdas, binds, etc.). +@see @RefSect{advanced_topics, Advanced Topics} */ typedef boost::function assertion_failure_handler; /** Set the precondition failure handler. +Set a new precondition failure handler and return the old one. + +@b Throws: @c noexcept (or @c throw() if no C++11). @param f New precondition failure handler functor. @return Old precondition failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ set_precondition_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW; + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Return the precondition failure handler. -@return Current precondition failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +This is often called only internally by this library. + +@b Throws: @c noexcept (or @c throw() if no C++11). +@return Precondition failure handler functor. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC -get_precondition_failure() BOOST_NOEXCEPT_OR_NOTHROW; +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ +get_precondition_failure() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Call the precondition hander functor. -This is typically only called internally by this library. -@param where Context of precondition failure. +This is often called only internally by this library. + +@b Throws: This can throw in case programmers specify a failure handler that + throws exceptions on precondition failures (not the default). +@param where Operation that failed preconditions (note that destructors + never have preconditions). + */ -void BOOST_CONTRACT_DETAIL_DECLSPEC +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ precondition_failure(from where) /* can throw */; /** Set the postcondition failure handler. +Set a new postcondition failure handler and return the old one. + +@b Throws: @c noexcept (or @c throw() if no C++11). @param f New postcondition failure handler functor. @return Old postcondition failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ set_postcondition_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW; + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Return the postcondition failure handler. -@return Current postcondition failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +This is often called only internally by this library. + +@b Throws: @c noexcept (or @c throw() if no C++11). +@return Postcondition failure handler functor. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC -get_postcondition_failure() BOOST_NOEXCEPT_OR_NOTHROW; +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ +get_postcondition_failure() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Call the postcondition hander functor. -This is typically only called internally by this library. -@param where Context of postcondition failure. +This is often called only internally by this library. + +@b Throws: This can throw in case programmers specify a failure handler that + throws exceptions on postcondition failures (not the default). +@param where Operation that failed postconditions (e.g., this might be useful + to program failure handler functors that never throw from + destructors, not even when they are programmed by users to throw + exceptions instead of terminating the program). */ -void BOOST_CONTRACT_DETAIL_DECLSPEC +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ postcondition_failure(from where) /* can throw */; /** Set the entry invariant failure handler. +Set a new entry invariant failure handler and return the old one. + +@b Throws: @c noexcept (or @c throw() if no C++11). @param f New entry invariant failure handler functor. @return Old entry invariant failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ set_entry_invariant_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW; + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Return the entry invariant failure handler. -@return Current entry invariant failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +This is often called only internally by this library. + +@b Throws: @c noexcept (or @c throw() if no C++11). +@return Entry invariant failure handler functor. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC -get_entry_invariant_failure() BOOST_NOEXCEPT_OR_NOTHROW; +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ +get_entry_invariant_failure() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Call the entry invariant hander functor. -This is typically only called internally by this library. -@param where Context of entry invariant failure. +This is often called only internally by this library. + +@b Throws: This can throw in case programmers specify a failure handler that + throws exceptions on entry invariant failures (not the default). +@param where Operation that failed entry invariants (e.g., this might be + useful to program failure handler functors that never throw from + destructors, not even when they are programmed by users to throw + exceptions instead of terminating the program). */ -void BOOST_CONTRACT_DETAIL_DECLSPEC +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ entry_invariant_failure(from where) /* can throw */; /** Set the exit invariant failure handler. +Set a new exit invariant failure handler and return the old one. + +@b Throws: @c noexcept (or @c throw() if no C++11). @param f New exit invariant failure handler functor. @return Old exit invariant failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} */ -assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC +assertion_failure_handler +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ set_exit_invariant_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW; + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Return the exit invariant failure handler. -@return Current exit invariant failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +This is often called only internally by this library. + +@b Throws: @c noexcept (or @c throw() if no C++11). +@return Exit invariant failure handler functor. +@see @RefSect{advanced_topics, Advanced Topics} */ assertion_failure_handler -BOOST_CONTRACT_DETAIL_DECLSPEC get_exit_invariant_failure() - BOOST_NOEXCEPT_OR_NOTHROW; +/** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ +get_exit_invariant_failure() + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** Call the exit invariant hander functor. -This is typically only called internally by this library. -@param where Context of exit invariant failure. +This is often called only internally by this library. + +@b Throws: This can throw in case programmers specify a failure handler that + throws exceptions on exit invariant failures (not the default). +@param where Operation that failed exit invariants (e.g., this might be + useful to program failure handler functors that never throw from + destructors, not even when they are programmed by users to throw + exceptions instead of terminating the program). */ -void BOOST_CONTRACT_DETAIL_DECLSPEC +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ exit_invariant_failure(from where) /* can throw */; /** -Set the both entry and exit invariant failure handlers at once (for -convenience). +Set both entry and exit invariant failure handlers at once (for convenience). +This is equivalent to calling both +@RefFunc{boost::contract::set_entry_invariant_failure}(f) and +@RefFunc{boost::contract::set_exit_invariant_failure}(f). + +@b Throws: @c noexcept (or @c throw() if no C++11). @param f New invariant failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} */ -void BOOST_CONTRACT_DETAIL_DECLSPEC +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ set_invariant_failure(assertion_failure_handler const& f) - BOOST_NOEXCEPT_OR_NOTHROW; + /** @cond */ OOST_NOEXCEPT_OR_NOTHROW /** @endcond */; /** -Set the all (precondition, postcondition, entry and exit invariant) failure -handlers at once (for convenience). -@param f New failure handler functor. -@see @RefSect{advanced_topics, Advanced Topics}. +Set the all contract failure handlers at once (for convenience). +This is equivalent to calling +@RefFunc{boost::contract::set_entry_invariant_failure}(f), +@RefFunc{boost::contract::set_precondition_failure}(f), +@RefFunc{boost::contract::set_exit_invariant_failure}(f), and +@RefFunc{boost::contract::set_postcondition_failure}(f). + +@b Throws: @c noexcept (or @c throw() if no C++11). +@param f New contract failure handler functor. +@see @RefSect{advanced_topics, Advanced Topics} */ -void BOOST_CONTRACT_DETAIL_DECLSPEC -set_failure(assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW; +void /** @cond */ BOOST_CONTRACT_DETAIL_DECLSPEC /** @endcond */ +set_failure(assertion_failure_handler const& f) + /** @cond */ BOOST_NOEXCEPT_OR_NOTHROW /** @endcond */; } } // namespace +/** @cond */ #if BOOST_CONTRACT_HEADER_ONLY #include #endif +/** @endcond */ #endif // #include guard diff --git a/include/boost/contract/core/set_nothing.hpp b/include/boost/contract/core/set_nothing.hpp deleted file mode 100644 index adaf947..0000000 --- a/include/boost/contract/core/set_nothing.hpp +++ /dev/null @@ -1,80 +0,0 @@ - -#ifndef BOOST_CONTRACT_SET_NOTHING_HPP_ -#define BOOST_CONTRACT_SET_NOTHING_HPP_ - -// Copyright (C) 2008-2016 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 -Used to prevent setting other contract conditions after postconditions. -*/ - -#include -#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - #include - #include -#endif -#include - -namespace boost { - namespace contract { - template - class set_precondition_old_postcondition; - - template - class set_old_postcondition; - - template - class set_postcondition_only; - } -} - -namespace boost { namespace contract { - -/** -Used to prevent setting other contract conditions after postconditions. -This class has no member function so it cannot be used to set any contract -functor. -*/ -class set_nothing { // Copyable (as *). -public: - /** Destruct this object. */ - ~set_nothing() BOOST_NOEXCEPT_IF(false) {} - - // No set member functions here. - -/** @cond */ -private: - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - typedef boost::contract::detail::check_base check_type; - - explicit set_nothing(check_type* check) : check_(check) {} - - boost::contract::detail::auto_ptr check_; - #endif - - // Friends (used to limit library's public API). - - friend class guard; - - template - friend class set_precondition_old_postcondition; - - template - friend class set_old_postcondition; - - template - friend class set_postcondition_only; -/** @endcond */ -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/set_old_postcondition.hpp b/include/boost/contract/core/set_old_postcondition.hpp deleted file mode 100644 index 2fa1631..0000000 --- a/include/boost/contract/core/set_old_postcondition.hpp +++ /dev/null @@ -1,140 +0,0 @@ - -#ifndef BOOST_CONTRACT_SET_OLD_POSTCONDITION_HPP_ -#define BOOST_CONTRACT_SET_OLD_POSTCONDITION_HPP_ - -// Copyright (C) 2008-2016 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 -Allow to specify old value assignments and postconditions. -*/ - -#include -#include -#include -#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - #include - #include - #include -#endif -#if !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) - #include -#endif -#include - -namespace boost { - namespace contract { - template - class set_precondition_old_postcondition; - } -} - -namespace boost { namespace contract { - -/** -Allow to specify old value assignments and postconditions. -Allow to program functors this library will call to assign old values before -body execution and to check postconditions. -@tparam R Return type of the function being contracted if that function is a - non-void virtual or overriding public function, otherwise this is - always @c void. -@see @RefSect{tutorial, Tutorial}, @RefSect{advanced_topics, Advances Topics}. -*/ -template -class set_old_postcondition { // Copyable (as *). -public: - /** Destruct this object. */ - ~set_old_postcondition() BOOST_NOEXCEPT_IF(false) {} - - /** - Allow to specify old value assignments to execute just before function body. - @param f Functor called by this library to assign old values. This - functor is called just before the function body is executed, but - after preconditions and class invariants are checked. Old values - are usually assigned using @RefMacro{BOOST_CONTRACT_OLDOF}. This - functor must be a nullary functor. This functor should capture - old value pointers (and in general all other variables) by - (constant) reference. - @return After old value assignments have been specified, return object that - allows to optionally specify postconditions. - */ - template - set_postcondition_only old(F const& f) { - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_old(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_postcondition_only(check_.release()); - #else - return set_postcondition_only(); - #endif - } - - /** - Allow to specify postconditions. - @param f Functor called by this library to check postconditions. Any - exception thrown by a call to this functor indicates a - postcondition failure. Assertions within this functor are - usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}. This - functor must be a nullary functor if @c R is @c void, otherwise - it must be unary functor taking the return value as a parameter - of type R const& (to avoid extra copies, or @c R and also - R const if extra copies of the return value are - irrelevant). This functor should capture variables by - (constant) reference. - @return After postconditions have been specified, return object that does - not allow to specify any additional contract (i.e., set nothing). - */ - template - set_nothing postcondition(F const& f) { - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_post(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_nothing(check_.release()); - #else - return set_nothing(); - #endif - } - -/** @cond */ -private: - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - typedef boost::contract::detail::check_pre_post::type> check_type; - - explicit set_old_postcondition(check_type* check) : check_(check) {} - - boost::contract::detail::auto_ptr check_; - #endif - - // Friends (used to limit library's public API). - - friend class guard; - - friend class set_precondition_old_postcondition; - - template - friend set_old_postcondition<> constructor(CC* oobj); - - template - friend set_old_postcondition<> destructor(CC* oobj); -/** @endcond */ -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/set_postcondition_only.hpp b/include/boost/contract/core/set_postcondition_only.hpp deleted file mode 100644 index b444bc3..0000000 --- a/include/boost/contract/core/set_postcondition_only.hpp +++ /dev/null @@ -1,110 +0,0 @@ - -#ifndef BOOST_CONTRACT_SET_POSTCONDITION_ONLY_HPP_ -#define BOOST_CONTRACT_SET_POSTCONDITION_ONLY_HPP_ - -// Copyright (C) 2008-2016 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 -Allow to specify postconditions. -*/ - -#include -#include -#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - #include - #include - #include -#endif -#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - #include -#endif -#include - -namespace boost { - namespace contract { - template - class set_precondition_old_postcondition; - - template - class set_old_postcondition; - } -} - -namespace boost { namespace contract { - -/** -Allow to specify postconditions. -Allow to program functors this library will call to check postconditions. -@tparam R Return type of the function being contracted if that function is a - non-void virtual or overriding public function, otherwise this is - always @c void. -@see @RefSect{tutorial, Tutorial}, @RefSect{advanced_topics, Advances Topics}. -*/ -template -class set_postcondition_only { // Copyable (as *). -public: - /** Destruct this object. */ - ~set_postcondition_only() BOOST_NOEXCEPT_IF(false) {} - - /** - Allow to specify postconditions. - @param f Functor called by this library to check postconditions. Any - exception thrown by a call to this functor indicates a - postcondition failure. Assertions within this functor are - usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}. This - functor must be a nullary functor if @c R is @c void, otherwise - it must be unary functor taking the return value as a parameter - of type R const& (to avoid extra copies, or @c R and also - R const if extra copies of the return value are - irrelevant). This functor should capture variables by - (constant) reference. - @return After postconditions have been specified, return object that does - not allow to specify any additional contract (i.e., set nothing). - */ - template - set_nothing postcondition(F const& f) { - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_post(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_nothing(check_.release()); - #else - return set_nothing(); - #endif - } - -/** @cond */ -private: - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - typedef boost::contract::detail::check_pre_post::type> check_type; - - explicit set_postcondition_only(check_type* check) : check_(check) {} - - boost::contract::detail::auto_ptr check_; - #endif - - // Friends (used to limit library's public API). - - friend class guard; - - friend class set_precondition_old_postcondition; - - friend class set_old_postcondition; -/** @endcond */ -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/set_precondition_old_postcondition.hpp b/include/boost/contract/core/set_precondition_old_postcondition.hpp deleted file mode 100644 index 79bffeb..0000000 --- a/include/boost/contract/core/set_precondition_old_postcondition.hpp +++ /dev/null @@ -1,186 +0,0 @@ - -#ifndef BOOST_CONTRACT_SET_PRECONDITION_OLD_POSTCONDITION_HPP_ -#define BOOST_CONTRACT_SET_PRECONDITION_OLD_POSTCONDITION_HPP_ - -// Copyright (C) 2008-2016 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 -Allow to specify preconditions, old value assignments, and postconditions. -*/ - -#include -#include -#include -#include -#include -#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - #include - #include - #include -#endif -#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) - #include -#endif -#include - -namespace boost { - namespace contract { - class virtual_; - } -} - -namespace boost { namespace contract { - -/** -Allow to specify preconditions, old value assignments, and postconditions. -Allow to program functors this library will call to check preconditions, assign -old values before body execution, and check postconditions. -@tparam R Return type of the function being contracted if that function is a - non-void virtual or overriding public function, otherwise this is - always @c void. -@see @RefSect{tutorial, Tutorial}, @RefSect{advanced_topics, Advances Topics}. -*/ -template< - typename R /* = void (already in fwd decl from decl.hpp) */ - #ifdef DOXYGEN - = void - #endif -> -class set_precondition_old_postcondition { // Copyable (as *). -public: - /** Destruct this object. */ - ~set_precondition_old_postcondition() BOOST_NOEXCEPT_IF(false) {} - - /** - Allow to specify preconditions. - @param f Functor called by this library to check preconditions. Any - exception thrown by a call to this functor indicates a - precondition failure. Assertions within this functor are usually - programmed using @RefMacro{BOOST_CONTRACT_ASSERT}. This functor - must be a nullary functor. This functor could capture variables - by value, or better by (constant) reference to avoid extra - copies. - @return After preconditions have been specified, return object that allows - to optionally specify old value assignments and postconditions. - */ - template - set_old_postcondition precondition(F const& f) { - #ifndef BOOST_CONTRACT_NO_PRECONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_pre(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_old_postcondition(check_.release()); - #else - return set_old_postcondition(); - #endif - } - - /** - Allow to specify old value assignments to execute just before function body. - @param f Functor called by this library to assign old values. This - functor is called just before the function body is executed, but - after preconditions and class invariants are checked. Old values - are usually assigned using @RefMacro{BOOST_CONTRACT_OLDOF}. This - functor must be a nullary functor. This functor should capture - old value pointers (and in general all other variables) by - (constant) reference. - @return After old value assignments have been specified, return object that - allows to optionally specify postconditions. - */ - template - set_postcondition_only old(F const& f) { - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_old(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_postcondition_only(check_.release()); - #else - return set_postcondition_only(); - #endif - } - - /** - Allow to specify postconditions. - @param f Functor called by this library to check postconditions. Any - exception thrown by a call to this functor indicates a - postcondition failure. Assertions within this functor are - usually programmed using @RefMacro{BOOST_CONTRACT_ASSERT}. This - functor must be a nullary functor if @c R is @c void, otherwise - it must be unary functor taking the return value as a parameter - of type R const& (to avoid extra copies, or @c R and also - R const if extra copies of the return value are - irrelevant). This functor should capture variables by - (constant) reference. - @return After postconditions have been specified, return object that does - not allow to specify any additional contract (i.e., set nothing). - */ - template - set_nothing postcondition(F const& f) { - #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - BOOST_CONTRACT_DETAIL_DEBUG(check_); - check_->set_post(f); - #endif - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_nothing(check_.release()); - #else - return set_nothing(); - #endif - } - -/** @cond */ -private: - #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ - !defined(BOOST_CONTRACT_NO_INVARIANTS) - typedef boost::contract::detail::check_pre_post::type> check_type; - - explicit set_precondition_old_postcondition(check_type* check) : - check_(check) {} - - boost::contract::detail::auto_ptr check_; - #endif - - // Friends (used to limit library's public API). - - friend class guard; - - friend set_precondition_old_postcondition<> function(); - - template - friend set_precondition_old_postcondition<> public_function(); - - template - friend set_precondition_old_postcondition<> public_function(CC* oobj); - - template - friend set_precondition_old_postcondition<> public_function( - virtual_* vv, CC* oobj); - - template - friend set_precondition_old_postcondition public_function( - virtual_* vv, RR& rr, CC* oobj); - - BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1, - OO, RR, FF, CC, AArgs, vv, rr, ff, oobj, aargs) -/** @endcond */ -}; - -} } // namespace - -#endif // #include guard - diff --git a/include/boost/contract/core/specify.hpp b/include/boost/contract/core/specify.hpp new file mode 100644 index 0000000..c423349 --- /dev/null +++ b/include/boost/contract/core/specify.hpp @@ -0,0 +1,456 @@ + +#ifndef BOOST_CONTRACT_SPECIFY_HPP_ +#define BOOST_CONTRACT_SPECIFY_HPP_ + +// Copyright (C) 2008-2016 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 +Facilities to specify preconditions, old value assignments, and postconditions. +*/ + +#include +#include +#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + #include + #include + #include + #include +#endif +#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) + #include +#endif +#include + +namespace boost { + namespace contract { + class virtual_; + + template + class specify_precondition_old_postcondition; + + template + class specify_old_postcondition; + + template + class specify_postcondition_only; + } +} + +namespace boost { namespace contract { + +/** +Used to prevent setting other contract conditions after postconditions. +This class has no member function so it is used to prevent specifying contract +functors. +@see @RefSect{tutorial, Tutorial} +*/ +class specify_nothing { // Copyable (as *). +public: + /** + Destruct this object. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + */ + ~specify_nothing() BOOST_NOEXCEPT_IF(false) {} + + // No set member functions here. + +/** @cond */ +private: + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + typedef boost::contract::detail::check_base check_type; + + explicit specify_nothing(check_type* check) : check_(check) {} + + boost::contract::detail::auto_ptr check_; + #endif + + // Friends (used to limit library's public API). + + friend class guard; + + template + friend class specify_precondition_old_postcondition; + + template + friend class specify_old_postcondition; + + template + friend class specify_postcondition_only; +/** @endcond */ +}; + +/** +Allow to specify postconditions. +Allow to program functors this library will call to check postconditions. +@see @RefSect{tutorial, Tutorial} +@tparam VirtualResult Return type of the contracted function if that is either + a virtual or an overriding public function, otherwise + this is always @c void. +*/ +template +class specify_postcondition_only { // Copyable (as *). +public: + /** + Destruct this object. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + */ + ~specify_postcondition_only() BOOST_NOEXCEPT_IF(false) {} + + /** + Allow to specify postconditions. + @param f Functor called by this library to check postconditions @c f(). + Postcondition assertions within this functor call are usually + programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any + exception thrown by a call to this functor indicates a + postcondition failure (and will result in this library calling + @RefFunc{boost::contract::postcondition_failure}). This + functor must be a nullary functor if @c VirtualResult is + @c void, otherwise it must be a unary functor taking the return + value as a parameter of type VirtualResult const& (to + avoid extra copies, or @c VirtualResult and also + VirtualResult const if extra copies of the return value + are irrelevant). This functor should capture variables by + (constant) references (to access the values they will have at + function exit). + @return After postconditions have been specified, return object that does + not allow to specify any additional contract. + */ + template + specify_nothing postcondition(F const& f) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_post(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_nothing(check_.release()); + #else + return specify_nothing(); + #endif + } + +/** @cond */ +private: + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + typedef boost::contract::detail::check_pre_post::type> check_type; + + explicit specify_postcondition_only(check_type* check) : + check_(check) {} + + boost::contract::detail::auto_ptr check_; + #endif + + // Friends (used to limit library's public API). + friend class guard; + friend class specify_precondition_old_postcondition; + friend class specify_old_postcondition; +/** @endcond */ +}; + +/** +Allow to specify old value assignments and postconditions. +Allow to program functors this library will call to assign old values before +body execution and to check postconditions. +@see @RefSect{tutorial, Tutorial} +@tparam VirtualResult Return type of the contracted function if that is either + a virtual or an overriding public function, otherwise + this is always @c void. +*/ +template +class specify_old_postcondition { // Copyable (as *). +public: + /** + Destruct this object. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + */ + ~specify_old_postcondition() BOOST_NOEXCEPT_IF(false) {} + + /** + Allow to specify old value assignments to execute just before the function + body. + In most cases, it should be sufficient to initialize old value pointers as + soon as they are declared so it should not be necessary to use this function + (see @RefSect{advanced_topics, Advanced Topics}). + @param f Functor called by this library to assign old values @c f(). This + functor is called just before the function body is executed, but + after precondition and class invariants are checked (when they + are specified). Old value pointers within this functor call are + usually assigned using @RefMacro{BOOST_CONTRACT_OLDOF}. Any + exception thrown by a call to this functor is handled as a + postcondition failure (and will result in this library calling + @RefFunc{boost::contract::postcondition_failure} because old + values are ultimately used to assert postconditions). This + functor must be a nullary functor. This functor should capture + old value pointers by references so they can be assigned (all + other variables needed to evaluate old value expressions can be + captured by (constant) value, or better by (constant) reference + to avoid extra copies). + @return After old value assignments have been specified, return object that + allows to optionally specify postconditions. + */ + template + specify_postcondition_only old(F const& f) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_old(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_postcondition_only(check_.release()); + #else + return specify_postcondition_only(); + #endif + } + + /** + Allow to specify postconditions. + @param f Functor called by this library to check postconditions @c f(). + Postcondition assertions within this functor call are usually + programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any + exception thrown by a call to this functor indicates a + postcondition failure (and will result in this library calling + @RefFunc{boost::contract::postcondition_failure}). This + functor must be a nullary functor if @c VirtualResult is + @c void, otherwise it must be a unary functor taking the return + value as a parameter of type VirtualResult const& (to + avoid extra copies, or @c VirtualResult and also + VirtualResult const if extra copies of the return value + are irrelevant). This functor should capture variables by + (constant) references (to access the values they will have at + function exit). + @return After postconditions have been specified, return object that does + not allow to specify any additional contract. + */ + template + specify_nothing postcondition(F const& f) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_post(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_nothing(check_.release()); + #else + return specify_nothing(); + #endif + } + +/** @cond */ +private: + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + typedef boost::contract::detail::check_pre_post::type> check_type; + + explicit specify_old_postcondition(check_type* check) : + check_(check) {} + + boost::contract::detail::auto_ptr check_; + #endif + + // Friends (used to limit library's public API). + + friend class guard; + friend class specify_precondition_old_postcondition; + + template + friend specify_old_postcondition<> constructor(C*); + + template + friend specify_old_postcondition<> destructor(C*); +/** @endcond */ +}; + +/** +Allow to specify preconditions, old value assignments, and postconditions. +Allow to program functors this library will call to check preconditions, assign +old values before body execution, and check postconditions. +@see @RefSect{tutorial, Tutorial} +@tparam VirtualResult Return type of the contracted function if that is either + a virtual or an overriding public function, otherwise + this is always @c void. +*/ +template< + typename VirtualResult /* = void (already in fwd decl from decl.hpp) */ + #ifdef DOXYGEN + = void + #endif +> +class specify_precondition_old_postcondition { // Copyable (as *). +public: + /** + Destruct this object. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + */ + ~specify_precondition_old_postcondition() BOOST_NOEXCEPT_IF(false) {} + + /** + Allow to specify preconditions. + @param f Functor called by this library to check preconditions @c f(). + Precondition assertions within this functor call are usually + programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any + exception thrown by a call to this functor indicates a + precondition failure (and will result in this library calling + @RefFunc{boost::contract::precondition_failure}). This functor + must be a nullary functor. This functor can capture variables by + (constant) value, or better by (constant) reference to avoid + extra copies. + @return After preconditions have been specified, return object that allows + to optionally specify old value assignments and postconditions. + */ + template + specify_old_postcondition precondition(F const& f) { + #ifndef BOOST_CONTRACT_NO_PRECONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_pre(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_old_postcondition(check_.release()); + #else + return specify_old_postcondition(); + #endif + } + + /** + Allow to specify old value assignments to execute just before the function + body. + In most cases, it should be sufficient to initialize old value pointers as + soon as they are declared so it should not be necessary to use this function + (see @RefSect{advanced_topics, Advanced Topics}). + @param f Functor called by this library to assign old values @c f(). This + functor is called just before the function body is executed, but + after precondition and class invariants are checked (when they + are specified). Old value pointers within this functor call are + usually assigned using @RefMacro{BOOST_CONTRACT_OLDOF}. Any + exception thrown by a call to this functor is handled as a + postcondition failure (and will result in this library calling + @RefFunc{boost::contract::postcondition_failure} because old + values are ultimately used to assert postconditions). This + functor must be a nullary functor. This functor should capture + old value pointers by references so they can be assigned (all + other variables needed to evaluate old value expressions can be + captured by (constant) value, or better by (constant) reference + to avoid extra copies). + @return After old value assignments have been specified, return object that + allows to optionally specify postconditions. + */ + template + specify_postcondition_only old(F const& f) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_old(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_postcondition_only(check_.release()); + #else + return specify_postcondition_only(); + #endif + } + + /** + Allow to specify postconditions. + @param f Functor called by this library to check postconditions @c f(). + Postcondition assertions within this functor call are usually + programmed using @RefMacro{BOOST_CONTRACT_ASSERT}, but any + exception thrown by a call to this functor indicates a + postcondition failure (and will result in this library calling + @RefFunc{boost::contract::postcondition_failure}). This + functor must be a nullary functor if @c VirtualResult is + @c void, otherwise it must be a unary functor taking the return + value as a parameter of type VirtualResult const& (to + avoid extra copies, or @c VirtualResult and also + VirtualResult const if extra copies of the return value + are irrelevant). This functor should capture variables by + (constant) references (to access the values they will have at + function exit). + @return After postconditions have been specified, return object that does + not allow to specify any additional contract. + */ + template + specify_nothing postcondition(F const& f) { + #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS + BOOST_CONTRACT_DETAIL_DEBUG(check_); + check_->set_post(f); + #endif + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + return specify_nothing(check_.release()); + #else + return specify_nothing(); + #endif + } + +/** @cond */ +private: + #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ + !defined(BOOST_CONTRACT_NO_INVARIANTS) + typedef boost::contract::detail::check_pre_post::type> check_type; + + explicit specify_precondition_old_postcondition(check_type* check) : + check_(check) {} + + boost::contract::detail::auto_ptr check_; + #endif + + // Friends (used to limit library's public API). + + friend class guard; + friend specify_precondition_old_postcondition<> function(); + + template + friend specify_precondition_old_postcondition<> public_function(); + + template + friend specify_precondition_old_postcondition<> public_function(C*); + + template + friend specify_precondition_old_postcondition<> public_function( + virtual_*, C*); + + template + friend specify_precondition_old_postcondition public_function( + virtual_*, VR&, C*); + + BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1, + O, VR, F, C, Args, v, r, f, obj, args) +/** @endcond */ +}; + +} } // namespace + +#endif // #include guard + diff --git a/include/boost/contract/core/virtual.hpp b/include/boost/contract/core/virtual.hpp index b41dd8c..fa4d50a 100644 --- a/include/boost/contract/core/virtual.hpp +++ b/include/boost/contract/core/virtual.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Used to contract virtual public functions. +Facility to declare virtual public functions with contracts. */ #include @@ -33,16 +33,27 @@ namespace boost { namespace boost { namespace contract { /** -Class to mark virtual public functions. -Virtual and overriding public functions contracted using this library must have -an extra parameter at the very end of their parameter list. This parameter must -be a pointer to this class and it must be assigned to @c 0 by default. (This -extra parameter is often named @c v in this documentation, but any name can be -used.) +Class to mark declarations of virtual public functions. +Virtual public functions (and therefore overriding public functions) contracted +using this library must have an extra parameter at the very end of their +parameter list. This parameter must be a pointer to this class and it must have +default value @c 0 (i.e., null). (This extra parameter is often named @c v in +this documentation, but any name can be used.) -Rationale: This extra parameter is internally used by this library to -recognize virtual public functions and implement subcontracting. -@see @RefSect{tutorial, Tutorial}. +This extra parameter does not alter the calling interface of the contracted +function because it is always the last parameter and it has a default value (so +it is always omitted when users call the contracted function). This extra +parameter must be passed to @RefFunc{boost::contract::public_function}, +@RefMacro{BOOST_CONTRACT_OLDOF}, and all other operations of this library that +require a pointer to @RefClass{boost::contract::virtual_}. A part from that, +this class is not intended to be directly used by programmers (and that is why +this class does not have any public member and it is not copyable). + +@b Rationale: This extra parameter is internally used by this library to + recognize virtual public functions to implement subcontracting + (@c virtual cannot be introspected using template + meta-programming techniques in C++). +@see @RefSect{tutorial, Tutorial} */ class virtual_ : private boost::noncopyable { // Avoid copy queue, stack, etc. /** @cond */ @@ -101,7 +112,7 @@ class virtual_ : private boost::noncopyable { // Avoid copy queue, stack, etc. std::queue > old_inits_; std::stack > old_copies_; - boost::any result_ptr_; + boost::any result_ptr_; // Result for virtual and overriding functions. char const* result_type_name_; bool result_optional_; #endif diff --git a/include/boost/contract/destructor.hpp b/include/boost/contract/destructor.hpp index 2264fb3..c6f74b8 100644 --- a/include/boost/contract/destructor.hpp +++ b/include/boost/contract/destructor.hpp @@ -21,24 +21,28 @@ namespace boost { namespace contract { /** Program contracts for destructors. -Used to specify postconditions and check class invariants for destructors -(destructors do not have preconditions). -@see @RefSect{tutorial, Tutorial}. -@param obj The destructor's object @c this. -@return The result of this function must be assigned to a local variable of type - @RefClass{boost::contract::guard} declared at the beginning of the - destructor definition (after specifying old value assignments and - postconditions if they are present). +This is used to specify postconditions, old value assignments at body, and check +class invariants for destructors (destructors cannot not have preconditions, see +@RefSect{contract_programming_overview, Contract Programming Overview}). + +For optimization, this can be omitted for destructors that do not have +postconditions when the enclosing class has no invariants. +@see @RefSect{tutorial, Tutorial} +@param obj The object @c this from the scope of the contracted destructor. +@return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the body + of the contracted destructor (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ -template -set_old_postcondition<> destructor(C* obj) { - // Must #if also on ..._PRECONDITIONS here because set_... is generic. +template +specify_old_postcondition<> destructor(Class* obj) { + // Must #if also on ..._PRECONDITIONS here because specify_... is generic. #if !defined(BOOST_CONTRACT_NO_DESTRUCTORS) || \ !defined(BOOST_CONTRACT_NO_PRECONDITIONS) - return set_old_postcondition<>( - new boost::contract::detail::destructor(obj)); + return specify_old_postcondition<>( + new boost::contract::detail::destructor(obj)); #else - return set_old_postcondition<>(); + return specify_old_postcondition<>(); #endif } diff --git a/include/boost/contract/detail/all_core_headers.hpp b/include/boost/contract/detail/all_core_headers.hpp index f1180f1..32e3290 100644 --- a/include/boost/contract/detail/all_core_headers.hpp +++ b/include/boost/contract/detail/all_core_headers.hpp @@ -22,10 +22,7 @@ #include #include #include -#include -#include -#include -#include +#include #include #endif // #include guard diff --git a/include/boost/contract/detail/check_guard.hpp b/include/boost/contract/detail/check_guard.hpp index af517d7..5e91a79 100644 --- a/include/boost/contract/detail/check_guard.hpp +++ b/include/boost/contract/detail/check_guard.hpp @@ -34,9 +34,11 @@ private: } } } // namespace +/** @cond Needed because this header included by other public headers. */ #if BOOST_CONTRACT_HEADER_ONLY #include #endif +/** @endcond */ #endif // #include guard diff --git a/include/boost/contract/detail/condition/check_pre_post.hpp b/include/boost/contract/detail/condition/check_pre_post.hpp index c61cb39..ea7e09d 100644 --- a/include/boost/contract/detail/condition/check_pre_post.hpp +++ b/include/boost/contract/detail/condition/check_pre_post.hpp @@ -41,18 +41,18 @@ namespace boost { namespace contract { namespace detail { -template +template class check_pre_post : public check_base { // Non-copyable base. public: explicit check_pre_post(boost::contract::from from) : check_base(from) {} #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS private: - typedef typename boost::mpl::if_, + typedef typename boost::mpl::if_, boost::optional::type>::type const&> const& + optional_value_type::type>::type const&> const& , - R const& + VR const& >::type r_type; BOOST_CONTRACT_DETAIL_CHECK_PRE_POST_DEF_( diff --git a/include/boost/contract/detail/condition/check_pre_post_inv.hpp b/include/boost/contract/detail/condition/check_pre_post_inv.hpp index 2267888..fef0f40 100644 --- a/include/boost/contract/detail/condition/check_pre_post_inv.hpp +++ b/include/boost/contract/detail/condition/check_pre_post_inv.hpp @@ -31,8 +31,8 @@ namespace boost { namespace contract { namespace detail { -template -class check_pre_post_inv : public check_pre_post { // Non-copyable base. +template +class check_pre_post_inv : public check_pre_post { // Non-copyable base. #if !defined(BOOST_CONTRACT_NO_INVARIANTS) && \ !defined(BOOST_CONTRACT_PERMISSIVE) BOOST_STATIC_ASSERT_MSG( @@ -95,7 +95,7 @@ class check_pre_post_inv : public check_pre_post { // Non-copyable base. public: // obj can be 0 for static member functions. explicit check_pre_post_inv(boost::contract::from from, C* obj) : - check_pre_post(from) + check_pre_post(from) #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ !defined(BOOST_CONTRACT_NO_INVARIANTS) diff --git a/include/boost/contract/detail/condition/check_subcontracted_pre_post_inv.hpp b/include/boost/contract/detail/condition/check_subcontracted_pre_post_inv.hpp index 64e8752..9ba3773 100644 --- a/include/boost/contract/detail/condition/check_subcontracted_pre_post_inv.hpp +++ b/include/boost/contract/detail/condition/check_subcontracted_pre_post_inv.hpp @@ -67,10 +67,10 @@ namespace check_subcontracted_pre_post_inv_ { class signal_not_checked {}; } -// O, R, F, and Args-i can be none types (but C cannot). +// O, VR, F, and Args-i can be none types (but C cannot). BOOST_CONTRACT_DETAIL_DECL_DETAIL_CHECK_SUBCONTRACTED_PRE_POST_INV_Z(1, - /* is_friend = */ 0, O, R, F, C, Args) : // Non-copyable base. - public check_pre_post_inv + /* is_friend = */ 0, O, VR, F, C, Args) : // Non-copyable base. + public check_pre_post_inv { #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ @@ -145,12 +145,12 @@ public: boost::contract::from from, boost::contract::virtual_* v, C* obj, - R& r + VR& r BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_TVARIADIC_FPARAMS_Z(1, BOOST_CONTRACT_MAX_ARGS, Args, &, args) ) : - check_pre_post_inv(from, obj) + check_pre_post_inv(from, obj) #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS , r_(r) #endif @@ -176,8 +176,8 @@ public: boost::contract::virtual_::no_action); #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS v_->result_ptr_ = &r_; - v_->result_type_name_ = typeid(R).name(); - v_->result_optional_ = is_optional::value; + v_->result_type_name_ = typeid(VR).name(); + v_->result_optional_ = is_optional::value; #endif } else v_ = 0; } @@ -275,7 +275,7 @@ private: } typedef typename boost::remove_reference::type>::type r_type; + optional_value_type::type>::type r_type; boost::optional r; // No result copy in this code. if(!base_call_) r = r_; else if(v_->result_optional_) { @@ -307,7 +307,7 @@ private: } } } - check_post_r(r); + check_post_r(r); } template @@ -450,7 +450,7 @@ private: #endif #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - R& r_; + VR& r_; #endif #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ !defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \ diff --git a/include/boost/contract/detail/decl.hpp b/include/boost/contract/detail/decl.hpp index 5e243d4..db1ad9a 100644 --- a/include/boost/contract/detail/decl.hpp +++ b/include/boost/contract/detail/decl.hpp @@ -23,26 +23,26 @@ #define BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ arity, is_friend, has_result, \ - O, R, F, C, Args, \ + O, VR, F, C, Args, \ v, r, f, obj, args \ ) \ template< \ class O \ BOOST_PP_COMMA_IF(has_result) \ - BOOST_PP_EXPR_IIF(has_result, typename R) \ + BOOST_PP_EXPR_IIF(has_result, typename VR) \ , typename F \ , class C \ BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ BOOST_CONTRACT_DETAIL_TVARIADIC_TPARAMS_Z(z, arity, Args) \ > \ BOOST_PP_EXPR_IIF(is_friend, friend) \ - boost::contract::set_precondition_old_postcondition< \ - BOOST_PP_EXPR_IIF(has_result, R)> \ + boost::contract::specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_result, VR)> \ /* no boost::contract:: here for friends (otherwise need fwd decl) */ \ public_function( \ boost::contract::virtual_* v \ BOOST_PP_COMMA_IF(has_result) \ - BOOST_PP_EXPR_IIF(has_result, R& r) \ + BOOST_PP_EXPR_IIF(has_result, VR& r) \ , F f \ , C* obj \ BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ @@ -51,16 +51,16 @@ #if BOOST_CONTRACT_DETAIL_TVARIADIC #define BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(z, \ - O, R, F, C, Args, \ + O, VR, F, C, Args, \ v, r, f, obj, args \ ) \ BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ ~, /* is_friend = */ 1, /* has_result = */ 0, \ - O, R, F, C, Args, v, r, f, obj, args \ + O, VR, F, C, Args, v, r, f, obj, args \ ); \ BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ ~, /* is_friend = */ 1, /* has_result = */ 1, \ - O, R, F, C, Args, v, r, f, obj, args \ + O, VR, F, C, Args, v, r, f, obj, args \ ); #else /* PRIVATE */ @@ -84,25 +84,25 @@ /* PUBLIC */ #define BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(z, \ - O, R, F, C, Args, \ + O, VR, F, C, Args, \ v, r, f, obj, args \ ) \ BOOST_PP_REPEAT_ ## z( \ BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), \ BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTION_, \ - (/* has_result = */ 0, O, R, F, C, Args, v, r, f, obj, args) \ + (/* has_result = */ 0, O, VR, F, C, Args, v, r, f, obj, args) \ ) \ BOOST_PP_REPEAT_ ## z( \ BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), \ BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTION_, \ - (/* has_result = */ 1, O, R, F, C, Args, v, r, f, obj, args) \ + (/* has_result = */ 1, O, VR, F, C, Args, v, r, f, obj, args) \ ) #endif #define BOOST_CONTRACT_DETAIL_DECL_DETAIL_CHECK_SUBCONTRACTED_PRE_POST_INV_Z( \ - z, is_friend, O, R, F, C, Args) \ + z, is_friend, O, VR, F, C, Args) \ template< \ - class O, typename R, typename F, class C \ + class O, typename VR, typename F, class C \ BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) \ BOOST_CONTRACT_DETAIL_TVARIADIC_TPARAMS_Z(z, \ BOOST_CONTRACT_MAX_ARGS, Args) \ @@ -120,8 +120,8 @@ namespace boost { namespace contract { class virtual_; - template - class set_precondition_old_postcondition; + template + class specify_precondition_old_postcondition; } } diff --git a/include/boost/contract/detail/operation/constructor.hpp b/include/boost/contract/detail/operation/constructor.hpp index 4f2166b..c416be7 100644 --- a/include/boost/contract/detail/operation/constructor.hpp +++ b/include/boost/contract/detail/operation/constructor.hpp @@ -26,9 +26,9 @@ namespace boost { namespace contract { namespace detail { // Ctor subcontracting impl via C++ obj construction mechanism. template class constructor : - public check_pre_post_inv { // Non-copyable base. + public check_pre_post_inv { // Non-copyable base. public: - explicit constructor(C* obj) : check_pre_post_inv( + explicit constructor(C* obj) : check_pre_post_inv( boost::contract::from_constructor, obj) {} private: diff --git a/include/boost/contract/detail/operation/destructor.hpp b/include/boost/contract/detail/operation/destructor.hpp index 6c1019c..dc07e5d 100644 --- a/include/boost/contract/detail/operation/destructor.hpp +++ b/include/boost/contract/detail/operation/destructor.hpp @@ -26,9 +26,9 @@ namespace boost { namespace contract { namespace detail { // Dtor subcontracting impl via C++ obj destruction mechanism. template class destructor : - public check_pre_post_inv { // Non-copyable base. + public check_pre_post_inv { // Non-copyable base. public: - explicit destructor(C* obj) : check_pre_post_inv( + explicit destructor(C* obj) : check_pre_post_inv( boost::contract::from_destructor, obj) {} private: diff --git a/include/boost/contract/detail/operation/function.hpp b/include/boost/contract/detail/operation/function.hpp index 5a62efa..483933f 100644 --- a/include/boost/contract/detail/operation/function.hpp +++ b/include/boost/contract/detail/operation/function.hpp @@ -23,9 +23,9 @@ namespace boost { namespace contract { namespace detail { // Used for free function, private and protected member functions. class function : - public check_pre_post { // Non-copyable base. + public check_pre_post { // Non-copyable base. public: - explicit function() : check_pre_post( + explicit function() : check_pre_post( boost::contract::from_function) {} private: diff --git a/include/boost/contract/detail/operation/public_function.hpp b/include/boost/contract/detail/operation/public_function.hpp index 77cec76..dfcbff0 100644 --- a/include/boost/contract/detail/operation/public_function.hpp +++ b/include/boost/contract/detail/operation/public_function.hpp @@ -29,26 +29,26 @@ namespace boost { namespace contract { namespace detail { template< - class O, typename R, typename F, class C + class O, typename VR, typename F, class C BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_TVARIADIC_TPARAMS_Z(1, BOOST_CONTRACT_MAX_ARGS, Args) > class public_function : // Non-copyable base. public check_subcontracted_pre_post_inv< - O, R, F, C + O, VR, F, C BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(1, BOOST_CONTRACT_MAX_ARGS, Args) > { public: explicit public_function( - boost::contract::virtual_* v, C* obj, R& r + boost::contract::virtual_* v, C* obj, VR& r BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_TVARIADIC_FPARAMS_Z(1, BOOST_CONTRACT_MAX_ARGS, Args, &, args) ) : check_subcontracted_pre_post_inv< - O, R, F, C + O, VR, F, C BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(1, BOOST_CONTRACT_MAX_ARGS, Args) diff --git a/include/boost/contract/detail/operation/public_static_function.hpp b/include/boost/contract/detail/operation/public_static_function.hpp index 9f0a926..ba587a8 100644 --- a/include/boost/contract/detail/operation/public_static_function.hpp +++ b/include/boost/contract/detail/operation/public_static_function.hpp @@ -29,10 +29,10 @@ namespace boost { namespace contract { namespace detail { // No subcontracting because static so no obj and no substitution principle. template class public_static_function : - public check_pre_post_inv { // Non-copyable base. + public check_pre_post_inv { // Non-copyable base. public: explicit public_static_function() : - check_pre_post_inv(boost::contract::from_function, + check_pre_post_inv(boost::contract::from_function, /* obj = */ 0) {} diff --git a/include/boost/contract/function.hpp b/include/boost/contract/function.hpp index e8b5810..c327cb0 100644 --- a/include/boost/contract/function.hpp +++ b/include/boost/contract/function.hpp @@ -21,41 +21,27 @@ namespace boost { namespace contract { /** Program contracts for non-member, private and protected functions. +This is used to specify preconditions, postconditions, and old value assignments +at body for non-member, private and protected functions (these functions never +check class invariants, see +@RefSect{contract_programming_overview, Contract Programming Overview}). -Allow to program preconditions and postconditions (both optional) for -non-member, private and protected functions (these functions never check -invariants or participate in subcontracting). -The result of this function must be assigned to a local variable of type -@RefClass{boost::contract::guard} at the scope of the function being contracted. - -@code - // Enclosing function scope. - boost::contract::guard c = boost::contract::function() - .precondition(...) // Optional. - .old(...) // Optional. - .postcondition(...) // Optional. - ; - ... // Enclosing function body. -@endcode - -For optimization purposes this can be avoided for functions that do not have +For optimization, this can be omitted for functions that do not have preconditions and postconditions. - -Where .precondition(...), .old(...), and -.postcondition(...) take nullary functors that assert preconditions, -assign old value pointers just before body execution (most of the times it -should be sufficient to assign these pointers where they are first declared -instead), and assert postconditions respectively. -@SeeAlso @RefSect{tutorial, Tutorial} +@see @RefSect{tutorial, Tutorial} +@return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the body + of the contracted function (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ -set_precondition_old_postcondition<> function() { - // Must #if also on ..._INVARIANTS here because set_... is generic. +specify_precondition_old_postcondition<> function() { + // Must #if also on ..._INVARIANTS here because specify_... is generic. #if !defined(BOOST_CONTRACT_NO_FUNCTIONS) || \ !defined(BOOST_CONTRACT_NO_INVARIANTS) - return set_precondition_old_postcondition<>( + return specify_precondition_old_postcondition<>( new boost::contract::detail::function()); #else - return set_precondition_old_postcondition<>(); + return specify_precondition_old_postcondition<>(); #endif } diff --git a/include/boost/contract/guard.hpp b/include/boost/contract/guard.hpp index 88b32d0..f01b65d 100644 --- a/include/boost/contract/guard.hpp +++ b/include/boost/contract/guard.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -RAII object that checks the contracts. +RAII object to check contracts. */ #include @@ -43,20 +43,22 @@ namespace boost { namespace contract { /** RAII object that checks the contracts. In general, this object checks entry invariants, preconditions, and assigns old -values when it is constructed. It then checks exit invariants and postconditions -when it is destructed. However, special attention in placed in marking sure -postconditions are checked only if the body did not throw an exception, -constructors never check entry invariants, destructor check exit invariants only -if their body throws, etc. (see also -@RefSect{contract_programming_overview, Contract Programming Overview}). -@see @RefSect{tutorial, Tutorial}. +values when it is constructed. Then it checks exit invariants and postconditions +when it is destructed. In addition, this object markes sure that postconditions +are checked only if the body does not throw an exception, constructors never +check entry invariants, destructors check exit invariants only if their bodies +throw an exception, static invariants are always checked at entry and exit, etc. +(see also @RefSect{contract_programming_overview, +Contract Programming Overview}). +@see @RefSect{tutorial, Tutorial} */ -class guard { // Non-copyable (but copy ctor ~= move via ptr release). +class guard { // Copy ctor only (as move via ptr release). public: /** - Construct this object copying it from specified one. + Construct this object copying it from the specified one. This object will check the contract, the copied-from object will not (i.e., - contract checking ownership is transfered to the this object). + contract checking ownership is transfered from the copied object to this + object). */ guard(guard const& other) // Copy ctor moves check_ pointer to dest. #if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \ @@ -67,101 +69,112 @@ public: {} /** - Construct this object from specified contract. - Check entry invariants (as they apply for specified contract). - Implicit so initialization operator @c = can be used. + Construct this object from the specified contract. + Check entry invariants (if they apply to the specified contract). + This constructor is not @c explicit so initializations can use operator @c = + syntax. - Throws: This can throw any exception (exception specification - noexcept(false)) to allow to configure this library - to throw on contract failure. - @param contract Contract to be guarded by this object. - @tparam R Return type of operation being contracted if that operation is a - non-void virtual or overriding public function, otherwise this - is always void. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + @param contract Contract to be checked. + @tparam VirtualResult Return type of the contracted function if that is + either a virtual or an overriding public function, + otherwise this is always @c void. */ - template - /* implicit */ guard(set_precondition_old_postcondition const& contract) + template + /* implicit */ guard(specify_precondition_old_postcondition + const& contract) #ifndef DOXYGEN - BOOST_CONTRACT_GUARD_CTOR_DEF_(set_precondition_old_postcondition) + BOOST_CONTRACT_GUARD_CTOR_DEF_( + specify_precondition_old_postcondition) #else ; #endif /** - Construct this object from specified contract. - Check entry invariants (as they apply for specified contract) and check + Construct this object from the specified contract. + Check entry invariants (if they apply to the specified contract) and check preconditions. - Implicit so initialization operator @c = can be used. + This constructor is not @c explicit so initializations can use operator @c = + syntax. - Throws: This can throw any exception (exception specification - noexcept(false)) to allow to configure this library - to throw on contract failure. - @param contract Contract to be guarded by this object. - @tparam R Return type of operation being contracted if that operation is a - non-void virtual or overriding public function, otherwise this - is always void. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + @param contract Contract to be checked. + @tparam VirtualResult Return type of the contracted function if that is + either a virtual or an overriding public function, + otherwise this is always @c void. */ - template - /* implicit */ guard(set_old_postcondition const& contract) + template + /* implicit */ guard(specify_old_postcondition const& + contract) #ifndef DOXYGEN - BOOST_CONTRACT_GUARD_CTOR_DEF_(set_old_postcondition) + BOOST_CONTRACT_GUARD_CTOR_DEF_(specify_old_postcondition) #else ; #endif /** - Construct this object from specified contract. - Check entry invariants (as they apply for specified contract), check + Construct this object from the specified contract. + Check entry invariants (if they apply to the specified contract) and check preconditions, and assign old values. - Implicit so initialization operator @c = can be used. + This constructor is not @c explicit so initializations can use operator @c = + syntax. - Throws: This can throw any exception (exception specification - noexcept(false)) to allow to configure this library - to throw on contract failure. - @param contract Contract to be guarded by this object. - @tparam R Return type of operation being contracted if that operation is a - non-void virtual or overriding public function, otherwise this - is always void. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + @param contract Contract to be checked. + @tparam VirtualResult Return type of the contracted function if that is + either a virtual or an overriding public function, + otherwise this is always @c void. */ - template - /* implicit */ guard(set_postcondition_only const& contract) + template + /* implicit */ guard(specify_postcondition_only const& + contract) #ifndef DOXYGEN - BOOST_CONTRACT_GUARD_CTOR_DEF_(set_postcondition_only) + BOOST_CONTRACT_GUARD_CTOR_DEF_( + specify_postcondition_only) #else ; #endif /** - Construct this object from specified contract. - Check entry invariants (as they apply for specified contract), check - preconditions, and assign old values. (In this case, the destructor of this - object will also check postconditions.) - Implicit so initialization operator @c = can be used. + Construct this object from the specified contract. + Check entry invariants (if they apply to the specified contract) and check + preconditions, and assign old values (plus the destructor of this object + will also check postconditions in this case). + This constructor is not @c explicit so initializations can use operator @c = + syntax. - Throws: This can throw any exception (exception specification - noexcept(false)) to allow to configure this library - to throw on contract failure. - @param contract Contract to be guarded by this object. - @tparam R Return type of operation being contracted if that operation is a - non-void virtual or overriding public function, otherwise this - is always void. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_precondition_failure}, etc.). + @param contract Contract to be checked. */ - /* implicit */ guard(set_nothing const& contract) + /* implicit */ guard(specify_nothing const& contract) #ifndef DOXYGEN - BOOST_CONTRACT_GUARD_CTOR_DEF_(set_nothing) + BOOST_CONTRACT_GUARD_CTOR_DEF_(specify_nothing) #else ; #endif /** - Destroy this object. - Check exit invariants (as they apply for specified contract). Check - postconditions (if the body did not throw and postconditions where - specified for the contract specified when constructing this object). + Destruct this object. + Check exit invariants (if they apply to the contract specified at + construction) and postconditions (if the body did not throw and + postconditions apply to the contract specified at construction). - Throws: This can throw any exception (exception specification - noexcept(false)) to allow to configure this library - to throw on contract failure. + @b Throws: This can throw (i.e., @c noexcept(false)) in case programmers + specify failure handlers that throw exceptions instead of + terminating the program (see + @RefFunc{boost::contract::set_postcondition_failure}, etc.). */ ~guard() BOOST_NOEXCEPT_IF(false) {} // Allow auto_ptr dtor to throw. diff --git a/include/boost/contract/old.hpp b/include/boost/contract/old.hpp index baccf4b..dab0dc5 100644 --- a/include/boost/contract/old.hpp +++ b/include/boost/contract/old.hpp @@ -8,7 +8,7 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Facilities for old values. +Facilities to support old values. */ #include @@ -66,21 +66,23 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro // NOTE: Leave this #defined the same regardless of ..._POSTCONDITIONS. /** -Macro typically used to copy old value expressions. -This is a variadic macro, program the old value expression copy manually on -compilers that do not support variadic macros (see -also @RefSect{advanced_topics, Advanced Topics}). -@see @RefSect{tutorial, Tutorial}. -@param ... This macro usually takes a single parameter as the expressions to - be assigned to the old value. However, in virtual or overriding - public functions where the extra +Macro typically used to copy an old value expression and assign it to an old +value pointer. +The expression expanded by this macro should be assigned to an old value +pointer of type @RefClass{boost::contract::old_ptr} or +@RefClass{boost::contract::old_ptr_noncopyable}. + +This is a variadic macro. On compilers that do not support variadic macros, +programmers can manually copy old value expressions without using this macro +(see @RefSect{advanced_topics, Advanced Topics}). +@see @RefSect{tutorial, Tutorial} +@param ... This macro usually takes a single parameter as the old value + expression to be copied. However, for virtual and overriding public + functions where the extra @RefClass{boost::contract::virtual_}* function parameter must be used, this macro takes two parameters: The first parameter is - the pointer to @RefClass{boost::contract::virtual_} and then the - old value expression to be copied. -@return The expression expanded by this macro should be assigned to an old - value pointer, either @RefClass{boost::contract::old_ptr} or - @RefClass{boost::contract::old_ptr_noncopyable}. + the pointer to @RefClass{boost::contract::virtual_} and the second + parameter is the old value expression to be copied. */ #define BOOST_CONTRACT_OLDOF(...) \ BOOST_PP_CAT( /* CAT(..., EMTPY()) required on MSVC */ \ @@ -98,12 +100,12 @@ also @RefSect{advanced_topics, Advanced Topics}). /** @cond */ namespace boost { namespace contract { - class unconvertible_old; + class old_value; } - // Needed because `unconvertible_old` incomplete type when trait used. + // Needed because `old_value` incomplete type when trait used. template<> - struct is_copy_constructible : true_type {}; + struct is_copy_constructible : true_type {}; } /** @endcond */ @@ -113,11 +115,15 @@ template class old_ptr_noncopyable; /** -Old value pointer (requires pointed old value type to be copyable). -@see @RefSect{tutorial, Tutorial}. -@tparam T Type of pointed old value. If this type is not copyable, this - pointer will always be left null and this library will generate a - compile-time error when this pointer is dereferenced of accessed. +Old value pointer (that requires the pointed old value type to be copy +constructible). +This is set to point to an actual old value via either +@RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old} (that is +why this class does not have public non-default constructors). +@see @RefSect{tutorial, Tutorial} +@tparam T Type of the pointed old value. This type must be copy constructible, + otherwise this pointer will always be null and this library will + generate a compile-time error if this pointer is dereferenced. */ template class old_ptr { /* copyable (as *) */ @@ -131,10 +137,10 @@ public: /** Dereference this old value pointer. This will generate a run-time error if this pointer is null and a - compile-time error if the pointed type is not copyable. + compile-time error if the pointed type @c T is not copy constructible. @return The old value (contract assertions should not change the state of - the program so the old value is always returned as a constant - reference and this member function is @c const). + the program so this member function is @c const and it returns the + old value as a constant reference). */ T const& operator*() const { BOOST_STATIC_ASSERT_MSG( @@ -146,13 +152,14 @@ public: } /** - Access the pointed old value. - This will generate a compile-time error if the pointed type is not copyable. + Structure-dereference this old value pointer. + This will generate a compile-time error if the pointed type @c T is not + copy constructible. @return The old value (contract assertions should not change the state of - the program so the old value is always returned as a pointer to - constant object and this member function is @c const). + the program so this member function is @c const and it returns the + old value as a constant pointer to a constant object). */ - T const* operator->() const { + T const* const operator->() const { BOOST_STATIC_ASSERT_MSG( boost::is_copy_constructible::value, "old_ptr requires T copy constructor, otherwise use old_ptr_noncopyable" @@ -164,7 +171,7 @@ public: BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr, !!ptr_) #else /** - Safe-bool operator. + Check if this old value pointer is null or not (safe-bool operator). @return True if this pointer is not null, false otherwise. */ explicit operator bool() const; @@ -179,17 +186,20 @@ private: boost::shared_ptr ptr_; - friend class convertible_old; + friend class old_pointer; friend class old_ptr_noncopyable; /** @endcond */ }; /** -Old value pointer (does not require pointed old value type to be copyable). -@see @RefSect{advanced_topics, Advanced Topics}. -@tparam T Type of pointed old value. If this type is not copyable, this - pointer will always be left null (but this library will not generate - compile-time errors when this pointer is dereferenced of accessed). +Old value pointer (that does not require the pointed old value type to be copy +constructible). +This is set to point to an actual old value via either +@RefMacro{BOOST_CONTRACT_OLDOF} or @RefFunc{boost::contract::make_old}. +@see @RefSect{advanced_topics, Advanced Topics} +@tparam T Type of pointed old value. If this type is not copy constructible, + this pointer will always be null (but this library will not generate + compile-time errors when this pointer is dereferenced). */ template class old_ptr_noncopyable { /* copyable (as *) */ @@ -201,23 +211,21 @@ public: old_ptr_noncopyable() {} /** - Construct this object from a old value pointer for copyable-only types. - Implicitly called when assign an object of this type to - @RefMacro{BOOST_CONTRACT_OLDOF}. + Construct this object from an old value pointer of copyable-only types. + This constructor is implicitly called by this library when assigning an + object of this type using @RefMacro{BOOST_CONTRACT_OLDOF}. @param other Copyable-only old value pointer. */ /* implicit */ old_ptr_noncopyable(old_ptr const& other) : ptr_(other.ptr_) {} - // Only const access (contracts should not change old values). - /** Dereference this old value pointer. This will generate a run-time error if this pointer is null (but no - compile-time error if the pointed type is not copyable). + compile-time error if the pointed type @c T is not copy constructible). @return The old value (contract assertions should not change the state of - the program so the old value is always returned as a constant - reference and this member function is @c const). + the program so this member function is @c const and it returns the + old vale as a constant reference). */ T const& operator*() const { BOOST_CONTRACT_DETAIL_DEBUG(ptr_); @@ -225,14 +233,14 @@ public: } /** - Access the pointed old value. - (This will not generate a compile-time error if the pointed type is not - copyable.) + Structure-dereference this old value pointer. + (This will not generate a compile-time error if the pointed type @c T is not + copy constructible.) @return The old value (contract assertions should not change the state of - the program so the old value is always returned as a pointer to - constant object and this member function is @c const). + the program so this member function is @c const and it returns the + old value as a constant pointer to a constant object). */ - T const* operator->() const { + T const* const operator->() const { return ptr_.operator->(); } @@ -240,7 +248,7 @@ public: BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_noncopyable, !!ptr_) #else /** - Safe-bool operator. + Check if this old value pointer is null or not (safe-bool operator). @return True if this pointer is not null, false otherwise. */ explicit operator bool() const; @@ -255,76 +263,89 @@ private: boost::shared_ptr ptr_; - friend class convertible_old; + friend class old_pointer; /** @endcond */ }; /** -Internally hold old value copies. -@see @RefSect{advanced_topics, Advanced Topics}. +Convert user expressions in old values. +This class is often only implicitly used by this library and it does not +explicitly appear in user code. + +On older compilers that cannot correctly deduce the +@c boost::is_copy_constructible trait, programmers can manually specialize that +trait to make sure that only old value types that are copy constructible are +actually copied (see the @c boost::is_copy_constructible documentation). +@see @RefSect{advanced_topics, Advanced Topics} */ -class unconvertible_old { // Copyable (as *). +class old_value { // Copyable (as *). public: // Following implicitly called by ternary operator `... ? ... : null_old()`. /** - Construct this object from the specified old value (for copyable old value - types). - The specified old value is copied one time and the related old value pointer - will not be null (as long as postconditions are being checked, see - @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS}). + Construct this object from the specified old value when the old value type + is copy constructible. + The specified old value is copied (one time only) and the related old value + pointer will be set to not null (no copy is made instead if postconditions + are not being checked, see @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS}). @tparam T Old value type. - @param old_value Old value to be copied. + @param old Old value to be copied. */ template - /* implicit */ unconvertible_old( - T const& old_value, + /* implicit */ old_value( + T const& old, typename boost::enable_if >::type* = 0 ) #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS - : ptr_(boost::make_shared(old_value)) // The one single T's copy. + : ptr_(boost::make_shared(old)) // The one single T's copy. #endif // Else, leave ptr_ null (and no copy of T). {} /** - Construct this object from the specified old value (for non-copyable old - value types). - The specified old value cannot and so it is not copied in this case, thus - the related old value pointer will always be null. + Construct this object from the specified old value when the old value type + is not copy constructible. + The specified old value cannot be copied in this case so it is not copied + and the related old value pointer will always be null. @tparam T Old value type. - @param old_value Old value (that will not be copied in this case). + @param old Old value (that will not be copied in this case). */ template - /* implicit */ unconvertible_old( - T const& old_value, + /* implicit */ old_value( + T const& old, typename boost::disable_if >::type* = 0 ) {} // Leave ptr_ null (and no copy of T). /** @cond */ private: - explicit unconvertible_old() {} + explicit old_value() {} #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS boost::shared_ptr ptr_; #endif - friend class convertible_old; + friend class old_pointer; - friend unconvertible_old null_old(); + friend old_value null_old(); /** @endcond */ }; /** -Internally convert old value copies to old value pointers. -@see @RefSect{advanced_topics, Advanced Topics}. +Convert old value copies to old value pointers. +This class is often used only implicitly by this library and it does not +explicitly appear in user code (that is why this class does not have public +constructors, etc.). +@see @RefSect{advanced_topics, Advanced Topics} */ -class convertible_old { // Copyable (as *). +class old_pointer { // Copyable (as *). public: /** - Convert this object to an old value pointer. - For example, implicitly called when assigning or initializing an old value - pointer. - @tparam T Type of pointed old value (might or might be copyable). + Convert this object to an old value pointer (the old value type might or not + be copy constructible). + For example, this is implicitly called when assigning or initializing old + value pointers. + @tparam T Type of the pointed old value. The old value pointer will always + be null if this type is not copy constructible (but this library + will not generate a compile-time error). */ template /* implicit */ operator old_ptr_noncopyable() { @@ -332,10 +353,13 @@ public: } /** - Convert this object to an old value pointer. - For example, implicitly called when assigning or initializing an old value - pointer. - @tparam T Type of pointed old value (must be copyable). + Convert this object to an old value pointer (the old value type must be + copy constructible). + For example, this is implicitly called when assigning or initializing old + value pointers. + @tparam T Type of the pointed old value. This type must be copy + constructible, otherwise this library will generate a compile-time + error if the old value pointer is dereferenced. */ template /* implicit */ operator old_ptr() { @@ -344,7 +368,7 @@ public: /** @cond */ private: - explicit convertible_old(virtual_* v, unconvertible_old const& old) + explicit old_pointer(virtual_* v, old_value const& old) #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS : v_(v), ptr_(old.ptr_) #endif @@ -408,45 +432,62 @@ private: boost::shared_ptr ptr_; #endif - friend convertible_old make_old(unconvertible_old const&); + friend old_pointer make_old(old_value const&); - friend convertible_old make_old(virtual_*, unconvertible_old const&); + friend old_pointer make_old(virtual_*, old_value const&); /** @endcond */ }; /** -Make a null old value copy (i.e., the related old value pointer will be null). -@see @RefSect{advanced_topics, Advanced Topics}. +Make a null old value copy. +The related old value pointer will always be null. +@see @RefSect{advanced_topics, Advanced Topics} +@return Null old value copy. */ -unconvertible_old null_old() { return unconvertible_old(); } +old_value null_old() { return old_value(); } /** -Make an old value copy (for non virtual and not overriding public functions). -@see @RefSect{advanced_topics, Advanced Topics}. -@param old Old value (implicitly and automatically wrapped in - @RefClass{boost::contract::uncovertible_old}). +Make an old value pointer (not to be used for for virtual and overriding public +functions). +The related old value pointer will not be null if the specified old value was +actually copied. +@see @RefSect{advanced_topics, Advanced Topics} +@param old Old value (usually implicitly constructed from the user old value + expression to be copied). +@return Old value pointer (usually implicitly converted to either + @RefClass{boost::contract::old_ptr} or + @RefClass{boost::contract::old_ptr_noncopyable} in user code). */ -convertible_old make_old(unconvertible_old const& old) { - return convertible_old(0, old); +old_pointer make_old(old_value const& old) { + return old_pointer(0, old); } /** -Make an old value copy (for virtual and overriding public functions). -@see @RefSect{advanced_topics, Advanced Topics}. -@param v Contracted virtual and overriding public function extra parameter. -@param old Old value (implicitly and automatically wrapped in - @RefClass{boost::contract::uncovertible_old}). +Make an old value pointer (to be used for virtual and overriding public +functions). +The related old value pointer will not be null if the specified old value was +actually copied. +@see @RefSect{advanced_topics, Advanced Topics} +@param v The contracted virtual and overriding function extra trailing + parameter of type @RefClass{boost::contract::virtual_}* and + with default value @c 0. +@param old Old value (usually implicitly constructed from the user old value + expression to be copied). +@return Old value pointer (usually implicitly converted to either + @RefClass{boost::contract::old_ptr} or + @RefClass{boost::contract::old_ptr_noncopyable} in user code). */ -convertible_old make_old(virtual_* v, unconvertible_old const& old) { - return convertible_old(v, old); +old_pointer make_old(virtual_* v, old_value const& old) { + return old_pointer(v, old); } /** -Return true if and only if old values need to be copied (for non virtual and -not overriding public functions). +Check if old values need to be copied (not to be used for virtual and overriding +public functions). For example, this function always returns false when postconditions are not being checked (see @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS}). -@see @RefSect{advanced_topics, Advanced Topics}. +@see @RefSect{advanced_topics, Advanced Topics} +@return True if old values are being copied, false otherwise. */ bool copy_old() { #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS @@ -457,12 +498,15 @@ bool copy_old() { } /** -Return true if and only if old values need to be copied (for virtual and -overriding public functions). +Check if old values need to be copied (to be used for virtual and overriding +public functions). For example, this function always returns false when postconditions are not being checked (see @RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS}). -@see @RefSect{advanced_topics, Advanced Topics}. -@param v Contracted virtual and overriding public function extra parameter. +@see @RefSect{advanced_topics, Advanced Topics} +@param v The contracted virtual and overriding function extra trailing + parameter of type @RefClass{boost::contract::virtual_}* and + with default value @c 0. +@return True if old values are being copied, false otherwise. */ bool copy_old(virtual_* v) { #ifndef BOOST_CONTRACT_NO_POSTCONDITIONS diff --git a/include/boost/contract/override.hpp b/include/boost/contract/override.hpp index badc128..83c0b98 100644 --- a/include/boost/contract/override.hpp +++ b/include/boost/contract/override.hpp @@ -8,7 +8,8 @@ // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html /** @file -Support contracts for overriding public functions. +Facilities to specify contracts for overriding public functions (to support +subcontracting). */ #include @@ -84,15 +85,15 @@ Support contracts for overriding public functions. }; #else /** - Declare override type allowing to explicitly specify its name. - Declare override type to be passed as an explicit template parameter to + Declare an override type with an arbitrary name. + Declare the override type to be passed as an explicit template parameter to @RefFunc{boost::contract::public_function} for overriding public functions. - @see @RefSect{tutorial, Tutorial}. - @param override_name Name of override type to be declared. + @see @RefSect{tutorial, Tutorial} + @param override_name Name of override type to declare. @param function_name Name of the overriding public function. This macro is called just once even if the function name is overloaded and the same override type can be used - for all overloaded functions (see + for all functions in the same overload set (see @RefSect{advanced_topics, Advanced Topics}). */ #define BOOST_CONTRACT_NAMED_OVERRIDE(override_name, function_name) \ @@ -102,14 +103,14 @@ Support contracts for overriding public functions. /* PUBLIC */ /** -Declare override type naming it override_function_name. -Declare override type to be passed as an explicit template parameter to +Declare an override type naming it override_function_name. +Declare the override type to be passed as an explicit template parameter to @RefFunc{boost::contract::public_function} for overriding public functions. -@see @RefSect{tutorial, Tutorial}. +@see @RefSect{tutorial, Tutorial} @param function_name Name of the overriding public function. This macro is called just once even if the function name is overloaded and the same override type can be used - for all overloaded functions (see + for all functions in the same overload set (see @RefSect{advanced_topics, Advanced Topics}). */ #define BOOST_CONTRACT_OVERRIDE(function_name) \ @@ -130,14 +131,14 @@ Declare override type to be passed as an explicit template parameter to /* PUBLIC */ /** - Declare multiple override types at once naming them override_.... - This is a variadic macro, call @RefMacro{BOOST_CONTRACT_OVERRIDE} multiple - times on compilers that do not support variadic macros instead. - @see @RefSect{tutorial, Tutorial}. + Declare multiple override types at once naming them override_... (for + convenience). + This is a variadic macro. On compilers that do not support variadic macros, + the override types can be programmed one-by-one calling + @RefMacro{BOOST_CONTRACT_OVERRIDE} for each function name. + @see @RefSect{tutorial, Tutorial} @param ... A comma separated list of one or more names of overriding - public functions. This macro is provided for convenience, it is - equivalent to calling @RefMacro{BOOST_CONTRACT_OVERRIDE} for - each specified function name. + public functions. */ #define BOOST_CONTRACT_OVERRIDES(...) \ BOOST_PP_SEQ_FOR_EACH(BOOST_CONTRACT_OVERRIDES_SEQ_, ~, \ diff --git a/include/boost/contract/public_function.hpp b/include/boost/contract/public_function.hpp index 6bc5cce..bda0bbd 100644 --- a/include/boost/contract/public_function.hpp +++ b/include/boost/contract/public_function.hpp @@ -9,8 +9,8 @@ /** @file Program contracts for public member functions. -Different overloads are provided to handle static, virtual void/non-void, and -overriding void/non-void public functions. +Overloads are provided to handle static, virtual void, virtual non-void, +overriding void, and override non-void public functions. */ // TODO: Document that even with variadic templates there's a hard limit to function max args (18 works, but MAX_ARGS=19 does not). This limit comes from Boost.MPL (vector, push_back, etc.), Boost.FunctionTypes, and other Boost algorithm that do not currently have a variadic template implementation. However, re-impl all these Boost alg would be too much work for this lib, plus the 19 max args limit seems high enough, and it would eventually be removed if Boost.MPL, Boost.FunctionTypes are ever ported to impl that use variadic templates. @@ -44,68 +44,79 @@ overriding void/non-void public functions. namespace boost { namespace contract { -// NOTE: O and (optionally) R allowed only when v is present because: +// 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., O -// 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 O (i.e., O +// 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 O. -// * R is only used for virtual functions (i.e., R might be present only if v -// is also present). -// However, R is never specified, not even for virtual functions, when the -// return type is void (i.e., R 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. -Used to specify preconditions, postconditions, old value assignments, and check -static class invariants for static public functions. -@see @RefSect{tutorial, Tutorial}. -@tparam C Class of contracted member function. This template parameter must - be explicitly specified for static public functions (because they - have no object so this template parameter cannot be automatically - deduced). -@return The result of this function must be assigned to a local variable of type - @RefClass{boost::contract::guard} declared at the beginning of the - static public function definition (after declaring old value pointers - if they are present). +This is used to specify preconditions, postconditions, old value assignments at +body, and check static class invariants for static public functions. + +For optimization, this can be omitted for static public functions that do not +have preconditions and postconditions when the enclosing class has no static +invariants. +@see @RefSect{tutorial, Tutorial} +@tparam Class The class of the contracted member function. 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 + automatically deduced). +@return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the body + of the contracted function (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ -template -set_precondition_old_postcondition<> public_function() { +template +specify_precondition_old_postcondition<> public_function() { #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS - return set_precondition_old_postcondition<>( - new boost::contract::detail::public_static_function()); + return specify_precondition_old_postcondition<>( + new boost::contract::detail::public_static_function()); #else - return set_precondition_old_postcondition<>(); + return specify_precondition_old_postcondition<>(); #endif } /** Program contracts for non-static, non-virtual, and not overriding public functions. -Used to specify preconditions, postconditions, old value assignments, and to -check class invariants for public functions that are not static, not virtual, -and do not override. -@see @RefSect{tutorial, Tutorial}. -@param obj The public function's object @c this. It will be @c const and/or - @c volatile depending on the cv-qualifier for the contracted public - function (volatile public functions will check volatile class - invariants, see also @RefSect{advanced_topics, Advanced Topics}). -@return The result of this function must be assigned to a local variable of type - @RefClass{boost::contract::guard} declared at the beginning of the - static public function definition (after declaring old value pointers - if they are present). +This is used to specify preconditions, postconditions, old value assignments at +body, and check class invariants for public functions that are not static, not +virtual, and do not override. + +For optimization, this can be omitted for public functions that do not have +preconditions and postconditions when the enclosing class has no (non-static) +invariants. +@see @RefSect{tutorial, Tutorial} +@param obj The object @c this from the scope of the contracted function. This + object can be @c const and @c volatile depending on the + cv-qualifier for the contracted function (volatile public functions + will check volatile class invariants, see also + @RefSect{advanced_topics, Advanced Topics}). +@return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the body + of the contracted function (otherwise this library will generate a + run-time error, see @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ -template -set_precondition_old_postcondition<> public_function(C* obj) { +template +specify_precondition_old_postcondition<> public_function(Class* obj) { #ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS - return set_precondition_old_postcondition<>( + return specify_precondition_old_postcondition<>( new boost::contract::detail::public_function< boost::contract::detail::none, boost::contract::detail::none, boost::contract::detail::none, - C + Class BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( BOOST_CONTRACT_MAX_ARGS) BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, @@ -125,7 +136,7 @@ set_precondition_old_postcondition<> public_function(C* obj) { ) ); #else - return set_precondition_old_postcondition<>(); + return specify_precondition_old_postcondition<>(); #endif } @@ -138,34 +149,36 @@ set_precondition_old_postcondition<> public_function(C* obj) { #define BOOST_CONTRACT_PUBLIC_FUNCTIONS_ 1 #endif -// TODO: Document no F here so cannot check consistency between R and actual func's result type... up to user to pass the right R... +// TODO: Document no F here so cannot check consistency between VirtualResult and actual func's result type... up to user to pass the right VirtualResult... // For non-static, virtual, and non-overriding public functions (PRIVATE macro). -#define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(has_result) \ +#define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_( \ + has_virtual_result) \ template< \ - BOOST_PP_EXPR_IIF(has_result, typename R) \ - BOOST_PP_COMMA_IF(has_result) \ - class C \ + BOOST_PP_EXPR_IIF(has_virtual_result, typename VirtualResult) \ + BOOST_PP_COMMA_IF(has_virtual_result) \ + class Class \ > \ - set_precondition_old_postcondition \ + specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)> \ public_function( \ virtual_* v \ - BOOST_PP_COMMA_IF(has_result) \ - BOOST_PP_EXPR_IIF(has_result, R& r) \ - , C* obj \ + 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_, \ - /* no F... so cannot enforce contracted F ret R (up to user) */ \ - return (set_precondition_old_postcondition< \ - BOOST_PP_EXPR_IIF(has_result, R)>( \ + /* no F... so cannot enforce contracted F returns VirtualResult */ \ + return (specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ new boost::contract::detail::public_function< \ boost::contract::detail::none, \ - BOOST_PP_IIF(has_result, \ - R \ + BOOST_PP_IIF(has_virtual_result, \ + VirtualResult \ , \ boost::contract::detail::none \ ), \ boost::contract::detail::none, \ - C \ + Class \ BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA( \ BOOST_CONTRACT_MAX_ARGS) \ BOOST_CONTRACT_DETAIL_NO_TVARIADIC_ENUM_Z(1, \ @@ -175,7 +188,7 @@ set_precondition_old_postcondition<> public_function(C* obj) { >( \ v, \ obj, \ - BOOST_PP_IIF(has_result, \ + BOOST_PP_IIF(has_virtual_result, \ r \ , \ boost::contract::detail::none::value() \ @@ -189,8 +202,8 @@ set_precondition_old_postcondition<> public_function(C* obj) { ) \ )); \ , \ - return set_precondition_old_postcondition< \ - BOOST_PP_EXPR_IIF(has_result, R)>(); \ + return specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ ) \ } @@ -198,68 +211,81 @@ set_precondition_old_postcondition<> public_function(C* obj) { #ifdef DOXYGEN /** - Program contracts for virtual but not overriding public functions returning + Program contracts for virtual, not overriding public functions returning void. - Used to specify preconditions, postconditions, old value assignments, and - to check class invariants for public functions that are virtual, do not - override, and return @c void. - @see @RefSect{tutorial, Tutorial}. + This is used to specify preconditions, postconditions, old value assignments + at body, and check class invariants for public functions that are virtual, + do not override, and return @c void. + + For optimization, this can be omitted for public functions that do not have + preconditions and postconditions when the enclosing class has no + (non-static) invariants. + @see @RefSect{tutorial, Tutorial} @param v The contracted virtual function extra trailing parameter of type @RefClass{boost::contract::virtual_}* and with default value @c 0. - @param obj The public function's object @c this. It will be @c const and/or - @c volatile depending on the cv-qualifier for the contracted - public function (volatile public functions will check volatile - class invariants, see also + @param obj The object @c this from the scope of the contracted function. + This object can be @c const and @c volatile depending on the + cv-qualifier for the contracted function (volatile public + functions will check volatile class invariants, see also @RefSect{advanced_topics, Advanced Topics}). - @return The result of this function must be assigned to a local variable of - type @RefClass{boost::contract::guard} declared at the beginning of - the static public function definition (after declaring old value - pointers if they are present). + @return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the + body of the contracted function (otherwise this library will + generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ - template - set_precondition_old_postcondition<> public_function(virtual_* v, C* obj); + template + specify_precondition_old_postcondition<> public_function(virtual_* v, + Class* obj); /** - Program contracts for virtual but not overriding public functions returning + Program contracts for virtual, not overriding public functions returning non-void. - Used to specify preconditions, postconditions, old value assignments, and - to check class invariants for public functions that are virtual, do not - override, and do not return @c void. - @see @RefSect{tutorial, Tutorial}. + This is used to specify preconditions, postconditions, old value assignments + at body, and check class invariants for public functions that are virtual, + do not override, and do not return @c void. + + For optimization, this can be omitted for public functions that do not have + preconditions and postconditions when the enclosing class has no + (non-static) invariants. + @see @RefSect{tutorial, Tutorial} @param v The contracted virtual function extra trailing parameter of type @RefClass{boost::contract::virtual_}* and with default value @c 0. @param r A reference to the contracted virtual function return value. - (This could be a variable local to the contracted function + (This can be a local variable within the contracted function scope, but it must be set by programmers at each function @c return statement.) - @param obj The public function's object @c this. It will be @c const and/or - @c volatile depending on the cv-qualifier for the contracted - public function (volatile public functions will check volatile - class invariants, see also + @param obj The object @c this from the scope of the contracted function. + This object can be @c const and @c volatile depending on the + cv-qualifier for the contracted function (volatile public + functions will check volatile class invariants, see also @RefSect{advanced_topics, Advanced Topics}). - @return The result of this function must be assigned to a local variable of - type @RefClass{boost::contract::guard} declared at the beginning of - the static public function definition (after declaring old value - pointers if they are present). + @return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the + body of the contracted function (otherwise this library will + generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ - template - set_precondition_old_postcondition public_function( - virtual_* v, R& r, C* obj); + template + specify_precondition_old_postcondition public_function( + virtual_* v, VirtualResult& r, Class* obj); #else - BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 0) - BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 1) + 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_result) \ + z, arity, arity_compl, has_virtual_result) \ BOOST_CONTRACT_DETAIL_DECL_OVERRIDING_PUBLIC_FUNCTION_Z(z, \ - arity, /* is_friend = */ 0, has_result, \ - O, R, F, C, Args, \ + arity, /* is_friend = */ 0, has_virtual_result, \ + Override, VirtualResult, F, Class, Args, \ v, r, f, obj, args \ ) { \ BOOST_PP_IIF(BOOST_CONTRACT_PUBLIC_FUNCTIONS_, \ @@ -271,8 +297,8 @@ set_precondition_old_postcondition<> public_function(C* obj) { BOOST_CONTRACT_DETAIL_TVARIADIC_SIZEOF(arity, Args), \ "missing one or more arguments for specified function" \ ); \ - /* assert consistency of F's result type and R (if has_result) */ \ - BOOST_PP_IIF(has_result, \ + /* assert consistency of F's result type and VirtualResult */ \ + BOOST_PP_IIF(has_virtual_result, \ BOOST_STATIC_ASSERT_MSG \ , \ BOOST_PP_TUPLE_EAT(2) \ @@ -281,26 +307,26 @@ set_precondition_old_postcondition<> public_function(C* obj) { typename boost::remove_reference::type>::type, \ typename boost::contract::detail:: \ - remove_value_reference_if_optional::type \ + remove_value_reference_if_optional::type\ >::value), \ "mismatching result type for specified function" \ ); \ /* assert this so lib can check and enforce override */ \ BOOST_STATIC_ASSERT_MSG( \ - boost::contract::access::has_base_types::value, \ + boost::contract::access::has_base_types::value, \ "enclosing class missing 'base-types' typedef" \ ); \ - return (set_precondition_old_postcondition< \ - BOOST_PP_EXPR_IIF(has_result, R)>( \ + return (specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>( \ new boost::contract::detail::public_function< \ - O, \ - BOOST_PP_IIF(has_result, \ - R \ + Override, \ + BOOST_PP_IIF(has_virtual_result, \ + VirtualResult \ , \ boost::contract::detail::none \ ), \ F, \ - C \ + Class \ BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \ BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, Args) \ BOOST_CONTRACT_DETAIL_NO_TVARIADIC_COMMA(arity_compl) \ @@ -309,7 +335,7 @@ set_precondition_old_postcondition<> public_function(C* obj) { >( \ v, \ obj, \ - BOOST_PP_IIF(has_result, \ + BOOST_PP_IIF(has_virtual_result, \ r \ , \ boost::contract::detail::none::value() \ @@ -322,8 +348,8 @@ set_precondition_old_postcondition<> public_function(C* obj) { ) \ )); \ , \ - return set_precondition_old_postcondition< \ - BOOST_PP_EXPR_IIF(has_result, R)>(); \ + return specify_precondition_old_postcondition< \ + BOOST_PP_EXPR_IIF(has_virtual_result, VirtualResult)>(); \ ) \ } @@ -331,87 +357,100 @@ set_precondition_old_postcondition<> public_function(C* obj) { #ifdef DOXYGEN /** - Program contracts for overriding (virtual or not) public functions returning + Program contracts for overriding public functions (virtual or not) returning void. - Used to specify preconditions, postconditions, old value assignments, and - to check class invariants for public functions that are virtual, do not - override, and return @c void. - @see @RefSect{tutorial, Tutorial}. + This is used to specify preconditions, postconditions, old value assignments + at body, and check class invariants for overriding public functions (virtual + or not) that return @c void. + + For optimization, this can be omitted for public functions that do not have + preconditions and postconditions when the enclosing class has no + (non-static) invariants. + @see @RefSect{tutorial, Tutorial} @param v The contracted virtual function extra trailing parameter of type @RefClass{boost::contract::virtual_}* and with default value @c 0. @param f A pointer to the contracted function. - @param obj The public function's object @c this. It will be @c const and/or - @c volatile depending on the cv-qualifier for the contracted - public function (volatile public functions will check volatile - class invariants, see also + @param obj The object @c this from the scope of the contracted function. + This object can be @c const and @c volatile depending on the + cv-qualifier for the contracted function (volatile public + functions will check volatile class invariants, see also @RefSect{advanced_topics, Advanced Topics}). - @param args The contracted function formal parameters (by reference and in - the oder they appear in the contracted function declaration). - On compilers that do not support variadic templates, this - library internally implements this function using preprocessor + @param args The contracted function arguments (by reference and in the oder + they appear in the contracted function declaration). 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 @p args is defined by @RefMacro{BOOST_CONTRACT_MAX_ARGS}). - @tparam O The overriding type @c override_... declared invoking the - @RefMacro{BOOST_CONTRACT_OVERRIDE} (or similar) macro with the - contracted function name. This template parameter must be - explicitly specified (because it is not used in this function - formal parameter so it cannot be automatically deduced). - @return The result of this function must be assigned to a local variable of - type @RefClass{boost::contract::guard} declared at the beginning of - the static public function definition (after declaring old value - pointers if they are present). + @tparam Override The type @c override_... declared using the + @RefMacro{BOOST_CONTRACT_OVERRIDE} (or similar) macro + using the contracted function name. This template + parameter must be explicitly specified (because there is + no function arguments from which this type template + parameter can be automatically deduced). + @return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the + body of the contracted function (otherwise this library will + generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ - template - set_precondition_old_postcondition<> public_function( - virtual_* v, F f, C* obj, Args&... args); + template + specify_precondition_old_postcondition<> public_function( + virtual_* v, F f, Class* obj, Args&... args); /** - Program contracts for overriding (virtual or not) public functions returning + Program contracts for overriding public functions (virtual or not) returning non-void. - Used to specify preconditions, postconditions, old value assignments, and - to check class invariants for public functions that are virtual, do not - override, and do not return @c void. - @see @RefSect{tutorial, Tutorial}. + This is used to specify preconditions, postconditions, old value assignments + at body, and check class invariants for overriding public functions (virtual + or not) that do not return @c void. + + For optimization, this can be omitted for public functions that do not have + preconditions and postconditions when the enclosing class has no + (non-static) invariants. + @see @RefSect{tutorial, Tutorial} @param v The contracted virtual function extra trailing parameter of type @RefClass{boost::contract::virtual_}* and with default value @c 0. @param r A reference to the contracted virtual function return value. - (This could be a variable local to the contracted function + (This can be a local variable within the contracted function scope, but it must be set by programmers at each function @c return statement.) @param f A pointer to the contracted function. - @param obj The public function's object @c this. It will be @c const and/or - @c volatile depending on the cv-qualifier for the contracted - public function (volatile public functions will check volatile - class invariants, see also + @param obj The object @c this from the scope of the contracted function. + This object can be @c const and @c volatile depending on the + cv-qualifier for the contracted function (volatile public + functions will check volatile class invariants, see also @RefSect{advanced_topics, Advanced Topics}). - @param args The contracted function formal parameters (by reference and in - the oder they appear in the contracted function declaration). - On compilers that do not support variadic templates, this - library internally implements this function using preprocessor + @param args The contracted function arguments (by reference and in the oder + they appear in the contracted function declaration). 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 @p args is defined by @RefMacro{BOOST_CONTRACT_MAX_ARGS}). - @tparam O The overriding type @c override_... declared invoking the - @RefMacro{BOOST_CONTRACT_OVERRIDE} (or similar) macro with the - contracted function name. This template parameter must be - explicitly specified (because it is not used in this function - formal parameter so it cannot be automatically deduced). - @return The result of this function must be assigned to a local variable of - type @RefClass{boost::contract::guard} declared at the beginning of - the static public function definition (after declaring old value - pointers if they are present). + @tparam Override The type @c override_... declared using the + @RefMacro{BOOST_CONTRACT_OVERRIDE} (or similar) macro + using the contracted function name. This template + parameter must be explicitly specified (because there is + no function arguments from which this type template + parameter can be automatically deduced). + @return The result of this function must be assigned to a variable of type + @RefClass{boost::contract::guard} declared locally just before the + body of the contracted function (otherwise this library will + generate a run-time error, see + @RefMacro{BOOST_CONTRACT_ON_MISSING_GUARD}). */ - template - set_precondition_old_postcondition public_function( - virtual_* v, R& r, F f, C* obj, Args&... args); + template + specify_precondition_old_postcondition 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_result = */ 0) - BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(1, - /* arity = */ ~, /* arity_compl = */ ~, /* has_result = */ 1) + 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 */ @@ -423,9 +462,9 @@ set_precondition_old_postcondition<> public_function(C* obj) { #define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDES_(z, \ arity, arity_compl, unused) \ BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ - arity, arity_compl, /* has_result = */ 0) \ + arity, arity_compl, /* has_virtual_result = */ 0) \ BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_(z, \ - arity, arity_compl, /* has_result = */ 1) + arity, arity_compl, /* has_virtual_result = */ 1) /* CODE */