finished very first draft of reference docs

This commit is contained in:
Lorenzo Caminiti
2016-05-18 19:51:45 -07:00
parent 1aa41fd14e
commit 3fef54b33e
36 changed files with 1981 additions and 431 deletions

View File

@@ -7,9 +7,11 @@
// 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 */
/** @file
Include all header files required by this library at once.
*/
// Include all and only public headers as users would (not core headers, etc.).
#include <boost/contract/detail/all_core_headers.hpp>
#include <boost/contract/assert.hpp>
#include <boost/contract/base_types.hpp>
#include <boost/contract/call_if.hpp>

View File

@@ -7,22 +7,39 @@
// 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 */
/** @file
Facilities to assert contract conditions.
*/
#include <boost/contract/detail/all_core_headers.hpp>
/* PUBLIC */
// Must use ternary operator expr here (instead of if-statement) so this macro
// can always be used with if-statements and all other C++ constructs.
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
!defined(BOOST_CONTRACT_NO_INVARIANTS)
#include <boost/preprocessor/stringize.hpp>
// Ternary operator used so this macro expand to an expression and it can
// be used with `if` and all other statements.
#define BOOST_CONTRACT_ASSERT(condition) \
((condition) ? (void*)0 : throw boost::contract::assertion_failure( \
__FILE__, __LINE__, BOOST_PP_STRINGIZE(condition)))
#else
/**
Preferred way to assert contract conditions.
Any exception thrown from within a preconditions, postcondition, and
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
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}.
@param condition The contract condition being checked.
*/
#define BOOST_CONTRACT_ASSERT(condition) /* nothing */
#endif

View File

@@ -9,7 +9,9 @@
// 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 */
/** @file
Facilities to specify base classes so to support subcontracting.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#include <boost/preprocessor/config/config.hpp>
@@ -21,6 +23,18 @@ 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.
*/
#define BOOST_CONTRACT_BASE_TYPES(...) void /* dummy type for typedef */
#else // contracts on

View File

@@ -7,6 +7,10 @@
// 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
Statically disable execution but also compilation of functor calls.
*/
// Do not include all_core_headers here (call_if is essentially standalone).
#include <boost/contract/detail/always_true.hpp>
#include <boost/contract/detail/none.hpp>
@@ -16,6 +20,8 @@
/* PRIVATE */
/** @cond */
// Boost.ResultOf not always able to deduce lambda result type (on MSVC).
#ifndef BOOST_NO_CXX11_DECL_TYPE
#include <boost/utility/declval.hpp>
@@ -27,43 +33,152 @@
typename boost::result_of<F()>::type
#endif
/** @endcond */
/* CODE */
namespace boost { namespace contract {
template<bool Cond, typename Then, typename R = boost::contract::detail::none>
/**
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.
@see @RefSect{advanced_topics, Advanced Topics}
@tparam Cond Static boolean condition controlling functor calls.
@tparam Then Type of functor to call when the static condition if true.
@tparam R Return type of then-branch functor.
*/
template<bool Cond, typename Then, typename R =
#ifndef DOXYGEN
boost::contract::detail::none
#else
unspecified
#endif
>
struct call_if_statement {}; // Empty so cannot be used (but copyable).
// Dispatch true condition (then) between non-void and void calls.
// IMPORTANT: result_of<Then()> can be evaluated only when condition is already
// checked to be true (as Then() is required to be valid only in that case) so
// this extra level of dispatching is necessary to avoid compiler errors.
/**
Template specialization to dispatch between then-branch functor calls that
return void and the ones that return non-void.
@note <c>result_of<Then()></c> 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.
@see @RefSect{advanced_topics, Advanced Topics}
@tparam Then Type of functor to call when the static condition if true.
*/
template<typename Then>
struct call_if_statement<true, Then, boost::contract::detail::none> :
call_if_statement<true, Then, // Copyable (as its base).
BOOST_CONTRACT_CALL_IF_RESULT_OF_(Then)>
{
struct call_if_statement<true, Then,
#ifndef DOXYGEN
boost::contract::detail::none
#else
unspecified
#endif
> :
call_if_statement<true, Then,
#ifndef DOXYGEN
BOOST_CONTRACT_CALL_IF_RESULT_OF_(Then)
#else
typename result_of<Then()>::type
#endif
>
{ // Copyable (as its base).
/**
Construct this object with the then-branch functor.
@param f Then-branch nullary functor, 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.
*/
explicit call_if_statement(Then f) : call_if_statement<true, Then,
BOOST_CONTRACT_CALL_IF_RESULT_OF_(Then)>(f) {}
};
// True condition (then) for non-void call.
/**
Template specialization to handle true static conditions for then-branch functor
calls returning non-void.
@see @RefSect{advanced_topics, Advanced Topics}
@tparam Then Type of functor to call when the static condition if true.
@tparam R Non-void return type of the then-branch functor call.
*/
template<typename Then, typename R>
struct call_if_statement<true, Then, R> { // 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.
*/
explicit call_if_statement(Then f) : r_(boost::make_shared<R>(f())) {}
operator R() const { return *r_; }
/** 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_; }
/**
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<typename Else>
R else_(Else const&) const { return *r_; }
R const& 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<typename Else>
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.
*/
template<bool ElseIfCond, typename ElseIfThen>
call_if_statement<true, Then, R> else_if_c(ElseIfThen const&) const {
call_if_statement<true, Then, R> 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.
*/
template<class ElseIfCond, typename ElseIfThen>
call_if_statement<true, Then, R> else_if(ElseIfThen const&) const {
call_if_statement<true, Then, R> else_if(ElseIfThen const& f) const {
return *this;
}
@@ -71,45 +186,149 @@ private:
boost::shared_ptr<R> r_;
};
// True condition (then) for void call.
/**
Template specialization to handle true static conditions for then-branch functor
calls returning void.
@see @RefSect{advanced_topics, Advanced Topics}
@tparam Then Type of functor to call when the static condition if true.
*/
template<typename Then>
struct call_if_statement<true, Then, void> { // 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.
*/
explicit call_if_statement(Then f) { f(); }
// Cannot provide `operator R()` here, because R 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.
*/
template<typename Else>
void else_(Else const&) const {}
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.
*/
template<bool ElseIfCond, typename ElseIfThen>
call_if_statement<true, Then, void> else_if_c(ElseIfThen const&) const {
call_if_statement<true, Then, void> 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 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.
*/
template<class ElseIfCond, typename ElseIfThen>
call_if_statement<true, Then, void> else_if(ElseIfThen const&) const {
call_if_statement<true, Then, void> else_if(ElseIfThen const& f) const {
return *this;
}
};
// False condition (else) for both non-void and void calls.
/**
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.
@see @RefSect{advanced_topics, Advanced Topics}
@tparam Then Type of functor to call when the static condition if true.
*/
template<typename Then> // Copyable (no data).
struct call_if_statement<false, Then, boost::contract::detail::none> {
explicit call_if_statement(Then const&) {}
struct call_if_statement<false, Then,
#ifndef DOXYGEN
boost::contract::detail::none
#else
unspecified
#endif
> {
/**
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.
*/
explicit call_if_statement(Then const& f) {}
// Do not provide `operator result_type()` here, require else_ instead.
// IMPORTANT: result_of<Else()> can be evaluated only when condition is
// already checked to be false (as Else() is required to be valid only in
// that case) so this is done lazily only in this template instantiation.
/**
Specify the else-branch functor.
@note <c>result_of<Else()></c> 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.
*/
template<typename Else>
BOOST_CONTRACT_CALL_IF_RESULT_OF_(Else) else_(Else f) const { return f(); }
#ifndef DOXYGEN
BOOST_CONTRACT_CALL_IF_RESULT_OF_(Else)
#else
typename result_of<Else()>::type
#endif
else_(Else f) const { return f(); }
/**
Specify an else-if-branch functor.
@param f Else-if-branch nullary functor, called and compiled if and only
if @c ElseIfCond is @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 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
functor call being compiled and executed.
*/
template<bool ElseIfCond, typename ElseIfThen>
call_if_statement<ElseIfCond, ElseIfThen> else_if_c(ElseIfThen f) const {
return call_if_statement<ElseIfCond, ElseIfThen>(f);
}
/**
Specify an else-if-branch functor.
@param f Else-if-branch nullary functor, called and compiled if and only
if @c ElseIfCond::value is @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 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
functor call being compiled and executed.
*/
template<class ElseIfCond, typename ElseIfThen>
call_if_statement<ElseIfCond::value, ElseIfThen> else_if(ElseIfThen f)
const {
@@ -117,22 +336,64 @@ struct call_if_statement<false, Then, boost::contract::detail::none> {
}
};
/**
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 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 condition controlling functor compilation and 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
functor call being compiled and executed.
*/
template<bool Cond, typename Then>
call_if_statement<Cond, Then> call_if_c(Then f) {
return call_if_statement<Cond, 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
functor call being compiled and executed.
*/
template<class Cond, typename Then>
call_if_statement<Cond::value, Then> call_if(Then f) {
return call_if_statement<Cond::value, 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).
*/
template<bool Cond, typename F>
bool check_if_c(F f) {
return call_if_c<Cond>(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).
*/
template<class Cond, typename F>
bool check_if(F f) {
return call_if_c<Cond::value>(f).else_(

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Program contracts for constructors.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#if !defined(BOOST_CONTRACT_NO_CONSTRUCTORS) || \
@@ -20,6 +22,17 @@
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.
*/
template<class C>
set_old_postcondition<> constructor(C* obj) {
// Must #if also on ..._PRECONDITIONS here because set_... is generic.
@@ -33,17 +46,42 @@ set_old_postcondition<> constructor(C* obj) {
}
// 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).
template<class C> // tparam avoids multiple instance of same base in user code.
/**
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.
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
@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).
*/
template<class C>
class constructor_precondition { // Copyable (no data).
public:
constructor_precondition() {} // For user ctor overloads with no pre.
/** Construct this object for constructor that do not have 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.
*/
template<typename F>
explicit constructor_precondition(F const& f) {
#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
if(boost::contract::detail::check_guard::checking()) return;
try {
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NOTHING
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
boost::contract::detail::check_guard checking;
#endif
f();

View File

@@ -7,6 +7,10 @@
// 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 declare invariants, base types, etc private members.
*/
#include <boost/contract/core/config.hpp>
#include <boost/contract/detail/decl.hpp>
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
@@ -40,14 +44,20 @@ namespace boost {
namespace boost { namespace contract {
// 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 simply fail SFINAE and no compiler error will be
// reported but invariants and subcontracting checking will be silently skipped
// at run-time. Therefore programmers must make sure to either declare contract
// members public or to make this class a friend.
/**
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.
*/
class access { // Copyable (as shell with no data member).
/** @cond */
// No public APIs (so users cannot use it directly by mistake).
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
@@ -124,6 +134,7 @@ class access { // Copyable (as shell with no data member).
BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
OO, RR, FF, CC, AArgs, vv, rr, ff, oobj, aargs)
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Configuration macros.
*/
// IMPORTANT: This header MUST NOT #include any other header of this lib.
// That way users can #include this header and not #include any of this lib
@@ -16,78 +18,229 @@
// TODO: Document that when contracts are programmed in .cpp and all these lib headers are #include only from within .cpp, then a given lib can be compiled for example without inv/post, only with pre. The code that will link to that lib will not be able to enable inv/post, or disable the pre. However, if contracts are programmed in .hpp and this lib headers are #included in .hpp that are shipped to users with a given lib, users of that lib can turn on/off all contracts for the shipped lib as well.
// BOOST_CONTRACT_DYN_LINK
// BOOST_CONTRACT_HEADER_ONLY
// Rationale: Named after BOOST_DISABLE_THREADS, BOOST_ASIO_DISABLE_THREADS, etc.
// BOOST_CONTRACT_DISABLE_THREADS
// Rationale: Named after BOOST_FUNCTION_MAX_ARGS, etc.
#ifndef BOOST_CONTRACT_MAX_ARGS
# define BOOST_CONTRACT_MAX_ARGS 10
#ifdef DOXYGEN
/**
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.
<b>Rationale:</b> 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).
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.
<b>Rationale:</b> Named after @c BOOST_CHRONO_HEADER_ONLY.
@see @RefSect{getting_started, Getting Started}.
*/
#define BOOST_CONTRACT_HEADER_ONLY
#endif
#ifdef DOXYGEN
/**
Define this macro to not lock internal library data for thread safety
(undefined by default).
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
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).
<b>Rationale:</b> Named after @c BOOST_DISABLE_THREADS,
@c BOOST_ASIO_DISABLE_THREADS, etc.
@see @RefSect{contract_programming_overview, Contract Programming Overview}.
*/
#define BOOST_CONTRACT_DISABLE_THREADS
#endif
#ifndef BOOST_CONTRACT_MAX_ARGS
/**
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.
@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
Boost libraries like Boost.MPL and Boost.FunctionTypes internally
used by this library).
<b>Rationale:</b> Named after @c BOOST_FUNCTION_MAX_ARGS, etc.
*/
#define BOOST_CONTRACT_MAX_ARGS 10
#endif
// Rationale: This cannot be called BASE_TYPES because BASE_TYPES(...) is already used as the macro to extract the public bases... so BASE_TYPEDEF seemed a reasonable naming alternative, but don't change base_types default #define because `typedef BASE_TYPES(...) base_types` is usually the best syntax in user's code.
#ifndef BOOST_CONTRACT_BASE_TYPEDEF
/**
Define the name of the base type @c typedef (@c base_types by default).
<b>Rationale:</b> 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
<c>typedef BOOST_CONTRACT_BASE_TYPES(...) base_types</c>
is the preferred syntax in user code).
*/
#define BOOST_CONTRACT_BASE_TYPEDEF base_types
#endif
#ifndef BOOST_CONTRACT_INVARIANT
/**
Define the name of the @c const and <c>const volatile</c> member functions
that checks mutable and volatile class invariants respectively (@c invariant
by default).
*/
#define BOOST_CONTRACT_INVARIANT invariant
#endif
// C++ does not allow to overload member functions based on static classifier,
// so a name different from the non-static class invariant member must be used.
#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 BOOST_CONTRACT_STATIC_INVARIANT static_invariant
#endif
// BOOST_CONTRACT_PERMISSIVE
#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,
<c>const volatile</c>, or <c>volatile const</c>.
@li A class that has contracts for one or more overriding public functions
must also define the @RefMacro{BOOST_CONTRACT_BASE_TYPES} @c typedef.
*/
#define BOOST_CONTRACT_PERMISSIVE
#endif
// Type of exception to throw is `guard c = ...` is missing. This is a
// programming error so by default this library calls abort. If this macro is
// #defined however, this library will throw the exception specified by the
// macro value instead of calling abort. When #defined, this macro must be a
// default constructible type.
// Code instruction(s) to execute when contracts are missing `guard c = ...`.
// In general, this is #undefined and this library calls `assert(false)` when
// contract guards are missing. Missing a contract guard is a logic error in
// the program (similar to dereferencing a null pointer) so terminating the
// program via `abort` or `assert` as this library does by default is the only
// safe thing to do. Therefore, it is recommended to never #define this macro.
// However, this macro can be defined to throw an exception, call a function,
// a no-op, or any other user code in case users truly need to handle missing
// contract guard logic errors without terminating the program, for example:
// #define BOOST_CONTRACT_ON_MISSING_GUARD { throw my_logic_error(); }
// (It can even be defined to expand to nothing.)
// BOOST_CONTRACT_ON_MISSING_GUARD
#ifdef DOXYGEN
/**
Code block to execute if <c>boost::contract::guard c = ...</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.
*/
#define OOST_CONTRACT_ON_MISSING_GUARD
#endif
// Contract checking is not disable while checking preconditions.
// This is what N1962 does by default. N1962 authors indicated it can be shown
// that unchecked arguments are passed to function bodies if contract checking
// is disable within precondition checking).
// However, not disabling contract checking while checking preconditions can
// lead to infinite recursive call in user code so by default this macro is
// not defined.
// TODO: Rename this BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTIONS
// BOOST_CONTRACT_PRECONDITIONS_DISABLE_NOTHING
#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 OOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
#endif
// BOOST_CONTRACT_NO_PRECONDITIONS
// BOOST_CONTRACT_NO_POSTCONDITIONS
#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}.
*/
#define BOOST_CONTRACT_NO_PRECONDITIONS
#endif
#if !defined(BOOST_CONTRACT_NO_ENTRY_INVARIANTS) && \
defined(BOOST_CONTRACT_NO_INVARIANTS)
#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}.
*/
#define BOOST_CONTRACT_NO_POSTCONDITIONS
#endif
#if defined(DOXYGEN) || (!defined(BOOST_CONTRACT_NO_ENTRY_INVARIANTS) && \
defined(BOOST_CONTRACT_NO_INVARIANTS))
/**
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).
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}.
*/
#define BOOST_CONTRACT_NO_ENTRY_INVARIANTS
#endif
#if !defined(BOOST_CONTRACT_NO_EXIT_INVARIANTS) && \
defined(BOOST_CONTRACT_NO_INVARIANTS)
#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
(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).
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}.
*/
#define BOOST_CONTRACT_NO_EXIT_INVARIANTS
#endif
#if !defined(BOOST_CONTRACT_NO_INVARIANTS) && \
defined(BOOST_CONTRACT_NO_ENTRY_INVARIANTS) && \
defined(BOOST_CONTRACT_NO_EXIT_INVARIANTS)
/**
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).
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}.
*/
#define BOOST_CONTRACT_NO_INVARIANTS
#endif
@@ -98,6 +251,21 @@
#error "define NO_ENTRY_INVARIANTS, NO_EXIT_INVARIANTS, and NO_POSTCONDITIONS instead"
#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
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},
@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}.
*/
#define BOOST_CONTRACT_NO_CONSTRUCTORS
#endif
@@ -105,6 +273,18 @@
#error "define NO_ENTRY_INVARIANTS, NO_EXIT_INVARIANTS, and NO_POSTCONDITIONS instead"
#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
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},
@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}.
*/
#define BOOST_CONTRACT_NO_DESTRUCTORS
#endif
@@ -113,6 +293,18 @@
#elif defined(BOOST_CONTRACT_NO_PRECONDITIONS) && \
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
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},
@RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS},
@RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and
@RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
#define BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
#endif
@@ -120,6 +312,17 @@
#error "define NO_PRECONDITIONS and NO_POSTCONDITIONS instead"
#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
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}.
*/
#define BOOST_CONTRACT_NO_FUNCTIONS
#endif
@@ -129,6 +332,18 @@
defined(BOOST_CONTRACT_NO_DESTRUCTORS) && \
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
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},
@RefMacro{BOOST_CONTRACT_NO_PRECONDITIONS},
@RefMacro{BOOST_CONTRACT_NO_EXIT_INVARIANTS}, and
@RefMacro{BOOST_CONTRACT_NO_POSTCONDITIONS} instead.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
#define BOOST_CONTRACT_NO_ALL
#endif

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Exception and utilities to report contract assertion failures.
*/
#include <boost/contract/detail/declspec.hpp>
#include <boost/function.hpp>
@@ -23,43 +25,121 @@
namespace boost { namespace contract {
// Placeholder base class to group all this lib exceptions.
// IMPORTANT: Must not inherit from std::exception as derived exceptions will.
/**
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}.
*/
class BOOST_CONTRACT_DETAIL_DECLSPEC exception {
public:
virtual ~exception();
/** Destruct this object. */
virtual ~exception() BOOST_NOEXCEPT_OR_NOTHROW;
};
// Rationale: boost::bad_any_cast exception does not print from/to type names,
// so throw custom exception.
/**
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.
<b>Rationale:</b> 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.
*/
explicit bad_virtual_result_cast(char const* from_type_name,
char const* to_type_name);
virtual ~bad_virtual_result_cast();
virtual char const* what() const BOOST_NOEXCEPT;
/** Destruct this object. */
virtual ~bad_virtual_result_cast() BOOST_NOEXCEPT_OR_NOTHROW;
/** Return an error description (containing both from and to type names). */
virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW;
/** @cond */
private:
std::string what_;
/** @endcond */
};
/**
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}.
*/
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).
@param file Name of the file containing the assertion (usually set using
<c>__FILE__</c>).
@param line Number of the line containing the assertion (usually set using
<c>__LINE__</c>).
@param code String text of the condition code being asserted.
*/
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.
*/
explicit assertion_failure(char const* const code);
virtual ~assertion_failure();
/** Destruct this object. */
virtual ~assertion_failure() BOOST_NOEXCEPT_OR_NOTHROW;
// Return something like `assertion "..." failed: file "...", line ...`.
virtual char const* what() const BOOST_NOEXCEPT;
/**
Return string describing the failed assertion.
@return Return a string similar to
<c>assertion "`code()`" failed: file "`file()`", line \`line()\`</c>
(parts of this information will be omitted if they were not
specified at construction).
*/
virtual char const* what() const BOOST_NOEXCEPT_OR_NOTHROW;
/**
Return assertion file.
@return 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).
*/
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).
*/
char const* const code() const;
/** @cond */
private:
void init();
@@ -67,63 +147,157 @@ private:
unsigned long const line_;
char const* const code_;
std::string what_;
/** @endcond */
};
enum from { from_constructor, from_destructor, from_function };
/**
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}.
*/
enum from {
/** Assertion failed in constructor contract. */
from_constructor,
/** Assertion failed in destructor contract. */
from_destructor,
/** Assertion failed in function (member or not) contract. */
from_function
};
// Use Boost.Function to handle also lambdas, binds, etc,
/**
Typef all assertion failure handler functions.
<b>Rationale:</b> Using Boost.Function to handle also lambdas, binds, etc.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
typedef boost::function<void (from)> assertion_failure_handler;
assertion_failure_handler
BOOST_CONTRACT_DETAIL_DECLSPEC set_precondition_failure(
assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
assertion_failure_handler
BOOST_CONTRACT_DETAIL_DECLSPEC get_precondition_failure()
/**
Set the precondition failure handler.
@param f New precondition failure handler functor.
@return Old precondition failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC
set_precondition_failure(assertion_failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW;
void BOOST_CONTRACT_DETAIL_DECLSPEC precondition_failure(from where)
/* can throw */;
/**
Return the precondition failure handler.
@return Current 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
BOOST_CONTRACT_DETAIL_DECLSPEC set_postcondition_failure(
assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
/**
Call the precondition hander functor.
This is typically only called internally by this library.
@param where Context of precondition failure.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
precondition_failure(from where) /* can throw */;
assertion_failure_handler
BOOST_CONTRACT_DETAIL_DECLSPEC get_postcondition_failure()
/**
Set the postcondition failure handler.
@param f New postcondition failure handler functor.
@return Old postcondition failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC
set_postcondition_failure(assertion_failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW;
void BOOST_CONTRACT_DETAIL_DECLSPEC postcondition_failure(from where)
/* can throw */;
/**
Return the postcondition failure handler.
@return Current postcondition failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC
get_postcondition_failure() BOOST_NOEXCEPT_OR_NOTHROW;
/**
Call the postcondition hander functor.
This is typically only called internally by this library.
@param where Context of postcondition failure.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
postcondition_failure(from where) /* can throw */;
/**
Set the entry invariant failure handler.
@param f New entry invariant failure handler functor.
@return Old entry invariant failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC
set_entry_invariant_failure(assertion_failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW;
/**
Return the entry invariant failure handler.
@return Current 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;
void BOOST_CONTRACT_DETAIL_DECLSPEC entry_invariant_failure(from where)
/* can throw */;
/**
Call the entry invariant hander functor.
This is typically only called internally by this library.
@param where Context of entry invariant failure.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
entry_invariant_failure(from where) /* can throw */;
/**
Set the exit invariant failure handler.
@param f New exit invariant failure handler functor.
@return Old exit invariant failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
assertion_failure_handler BOOST_CONTRACT_DETAIL_DECLSPEC
set_exit_invariant_failure(assertion_failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW;
/**
Return the exit invariant failure handler.
@return Current 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;
void BOOST_CONTRACT_DETAIL_DECLSPEC exit_invariant_failure(from where)
/* can throw */;
/**
Call the exit invariant hander functor.
This is typically only called internally by this library.
@param where Context of exit invariant failure.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
exit_invariant_failure(from where) /* can throw */;
// Set all inv failures (entry inv and exit inv) at once.
void BOOST_CONTRACT_DETAIL_DECLSPEC set_invariant_failure(
assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
/**
Set the both entry and exit invariant failure handlers at once (for
convenience).
@param f New invariant failure handler functor.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
set_invariant_failure(assertion_failure_handler const& f)
BOOST_NOEXCEPT_OR_NOTHROW;
// Set all failures (pre, post, entry inv, and exit int) at once.
void BOOST_CONTRACT_DETAIL_DECLSPEC set_failure(
assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
/**
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}.
*/
void BOOST_CONTRACT_DETAIL_DECLSPEC
set_failure(assertion_failure_handler const& f) BOOST_NOEXCEPT_OR_NOTHROW;
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Used to prevent setting other contract conditions after postconditions.
*/
#include <boost/contract/core/config.hpp>
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
@@ -33,12 +35,19 @@ namespace boost {
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) || \
@@ -62,6 +71,7 @@ private:
template<typename RR>
friend class set_postcondition_only;
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Allow to specify old value assignments and postconditions.
*/
#include <boost/contract/core/set_postcondition_only.hpp>
#include <boost/contract/core/set_nothing.hpp>
@@ -32,12 +34,34 @@ namespace boost {
}
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<typename R = void>
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<typename F>
set_postcondition_only<R> old(F const& f) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -53,6 +77,21 @@ public:
#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 <c>R const&</c> (to avoid extra copies, or @c R and also
<c>R const</c> 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<typename F>
set_nothing postcondition(F const& f) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -68,6 +107,7 @@ public:
#endif
}
/** @cond */
private:
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
@@ -91,6 +131,7 @@ private:
template<class CC>
friend set_old_postcondition<> destructor(CC* oobj);
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Allow to specify postconditions.
*/
#include <boost/contract/core/set_nothing.hpp>
#include <boost/contract/core/config.hpp>
@@ -34,12 +36,36 @@ namespace boost {
}
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<typename R = void>
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 <c>R const&</c> (to avoid extra copies, or @c R and also
<c>R const</c> 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<typename F>
set_nothing postcondition(F const& f) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -55,6 +81,7 @@ public:
#endif
}
/** @cond */
private:
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
@@ -74,6 +101,7 @@ private:
friend class set_precondition_old_postcondition<R>;
friend class set_old_postcondition<R>;
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Allow to specify preconditions, old value assignments, and postconditions.
*/
#include <boost/contract/core/set_old_postcondition.hpp>
#include <boost/contract/core/set_postcondition_only.hpp>
@@ -34,12 +36,39 @@ namespace boost {
}
namespace boost { namespace contract {
template<typename R /* = void (already in fwd decl from decl.hpp) */>
/**
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<typename F>
set_old_postcondition<R> precondition(F const& f) {
#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
@@ -55,6 +84,18 @@ public:
#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<typename F>
set_postcondition_only<R> old(F const& f) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -70,6 +111,21 @@ public:
#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 <c>R const&</c> (to avoid extra copies, or @c R and also
<c>R const</c> 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<typename F>
set_nothing postcondition(F const& f) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -85,6 +141,7 @@ public:
#endif
}
/** @cond */
private:
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
@@ -120,6 +177,7 @@ private:
BOOST_CONTRACT_DETAIL_DECL_FRIEND_OVERRIDING_PUBLIC_FUNCTIONS_Z(1,
OO, RR, FF, CC, AArgs, vv, rr, ff, oobj, aargs)
/** @endcond */
};
} } // namespace

View File

@@ -7,6 +7,10 @@
// 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 contract virtual public functions.
*/
#include <boost/contract/core/config.hpp>
#include <boost/contract/detail/decl.hpp>
#include <boost/noncopyable.hpp>
@@ -28,7 +32,20 @@ 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.)
<b>Rationale:</b> This extra parameter is internally used by this library to
recognize virtual public functions and implement subcontracting.
@see @RefSect{tutorial, Tutorial}.
*/
class virtual_ : private boost::noncopyable { // Avoid copy queue, stack, etc.
/** @cond */
// No public API (so users cannot use it directly by mistake).
enum action_enum {
@@ -97,6 +114,7 @@ class virtual_ : private boost::noncopyable { // Avoid copy queue, stack, etc.
BOOST_CONTRACT_DETAIL_DECL_DETAIL_CHECK_SUBCONTRACTED_PRE_POST_INV_Z(1,
/* is_friend = */ 1, OO, RR, FF, CC, AArgs);
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Program contracts for destructors.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#if !defined(BOOST_CONTRACT_NO_DESTRUCTORS) || \
@@ -17,6 +19,17 @@
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).
*/
template<class C>
set_old_postcondition<> destructor(C* obj) {
// Must #if also on ..._PRECONDITIONS here because set_... is generic.

View File

@@ -35,7 +35,7 @@ private:
if(check_guard::checking()) return;
#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
{
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NOTHING
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
check_guard checking;
#endif
this->check_pre();

View File

@@ -76,7 +76,7 @@ private:
this->check_subcontracted_entry_inv();
#endif
#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NOTHING
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
this->check_subcontracted_pre();
} // Release check guard.
#else

View File

@@ -50,7 +50,7 @@ private:
this->check_entry_static_inv();
#endif
#ifndef BOOST_CONTRACT_NO_PRECONDITIONS
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NOTHING
#ifndef BOOST_CONTRACT_PRECONDITIONS_DISABLE_NO_ASSERTION
this->check_pre();
} // Release check guard.
#else

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Program contracts for non-member, private, and protected functions.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#if !defined(BOOST_CONTRACT_NO_FUNCTIONS) || \
@@ -17,6 +19,35 @@
namespace boost { namespace contract {
/**
Program contracts for non-member, private and protected functions.
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
preconditions and postconditions.
Where <c>.precondition(...)</c>, <c>.old(...)</c>, and
<c>.postcondition(...)</c> 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}
*/
set_precondition_old_postcondition<> function() {
// Must #if also on ..._INVARIANTS here because set_... is generic.
#if !defined(BOOST_CONTRACT_NO_FUNCTIONS) || \

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
RAII object that checks the contracts.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#include <boost/contract/detail/condition/check_base.hpp>
@@ -17,6 +19,8 @@
/* PRIVATE */
/** @cond */
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
!defined(BOOST_CONTRACT_NO_INVARIANTS)
@@ -30,19 +34,30 @@
#define BOOST_CONTRACT_GUARD_CTOR_DEF_(contract_type) {}
#endif
// Following implicit to allow syntax `guard c = ...`.
#define BOOST_CONTRACT_GUARD_CTOR_(contract_type) \
/* implicit */ guard(contract_type const& contract) \
BOOST_CONTRACT_GUARD_CTOR_DEF_(contract_type)
/** @endcond */
/* CODE */
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}.
*/
class guard { // Non-copyable (but copy ctor ~= move via ptr release).
public:
// Following copy and implicit type conversion ctors allow `guard c = ...`.
/**
Construct this object copying it from 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).
*/
guard(guard const& other) // Copy ctor moves check_ pointer to dest.
#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
!defined(BOOST_CONTRACT_NO_POSTCONDITIONS) || \
@@ -51,19 +66,106 @@ public:
#endif
{}
template<typename R>
BOOST_CONTRACT_GUARD_CTOR_(set_precondition_old_postcondition<R>)
template<typename R>
BOOST_CONTRACT_GUARD_CTOR_(set_old_postcondition<R>)
template<typename R>
BOOST_CONTRACT_GUARD_CTOR_(set_postcondition_only<R>)
BOOST_CONTRACT_GUARD_CTOR_(set_nothing)
/**
Construct this object from specified contract.
Check entry invariants (as they apply for specified contract).
Implicit so initialization operator @c = can be used.
<b>Throws:</b> This can throw any exception (exception specification
<c>noexcept(false)</c>) 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.
*/
template<typename R>
/* implicit */ guard(set_precondition_old_postcondition<R> const& contract)
#ifndef DOXYGEN
BOOST_CONTRACT_GUARD_CTOR_DEF_(set_precondition_old_postcondition<R>)
#else
;
#endif
/**
Construct this object from specified contract.
Check entry invariants (as they apply for specified contract) and check
preconditions.
Implicit so initialization operator @c = can be used.
<b>Throws:</b> This can throw any exception (exception specification
<c>noexcept(false)</c>) 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.
*/
template<typename R>
/* implicit */ guard(set_old_postcondition<R> const& contract)
#ifndef DOXYGEN
BOOST_CONTRACT_GUARD_CTOR_DEF_(set_old_postcondition<R>)
#else
;
#endif
/**
Construct this object from specified contract.
Check entry invariants (as they apply for specified contract), check
preconditions, and assign old values.
Implicit so initialization operator @c = can be used.
<b>Throws:</b> This can throw any exception (exception specification
<c>noexcept(false)</c>) 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.
*/
template<typename R>
/* implicit */ guard(set_postcondition_only<R> const& contract)
#ifndef DOXYGEN
BOOST_CONTRACT_GUARD_CTOR_DEF_(set_postcondition_only<R>)
#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.
<b>Throws:</b> This can throw any exception (exception specification
<c>noexcept(false)</c>) 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.
*/
/* implicit */ guard(set_nothing const& contract)
#ifndef DOXYGEN
BOOST_CONTRACT_GUARD_CTOR_DEF_(set_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).
<b>Throws:</b> This can throw any exception (exception specification
<c>noexcept(false)</c>) to allow to configure this library
to throw on contract failure.
*/
~guard() BOOST_NOEXCEPT_IF(false) {} // Allow auto_ptr dtor to throw.
/** @cond */
private:
guard& operator=(guard const&); // Cannot copy outside of `guard c = ...`.
@@ -73,6 +175,7 @@ private:
boost::contract::detail::auto_ptr<boost::contract::detail::check_base>
check_;
#endif
/** @endcond */
};
} } // namespace

View File

@@ -7,7 +7,9 @@
// 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 */
/** @file
Facilities for old values.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#include <boost/contract/detail/check_guard.hpp>
@@ -35,6 +37,8 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro
/* PRIVATE */
/** @cond */
#ifdef BOOST_NO_CXX11_AUTO_DECLARATIONS
#define BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value) /* nothing */
#else
@@ -55,10 +59,29 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro
BOOST_CONTRACT_OLDOF_AUTO_TYPEOF_(value)(boost::contract::make_old( \
boost::contract::copy_old() ? (value) : boost::contract::null_old() \
))
/** @endcond */
/* PUBLIC */
// 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
@RefClass{boost::contract::virtual_}<c>*</c> 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}.
*/
#define BOOST_CONTRACT_OLDOF(...) \
BOOST_PP_CAT( /* CAT(..., EMTPY()) required on MSVC */ \
BOOST_PP_OVERLOAD( \
@@ -72,30 +95,47 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro
/* CODE */
// Specialization because `unconvertible_old` incomplete type when trait used.
/** @cond */
namespace boost {
namespace contract {
class unconvertible_old;
}
// Needed because `unconvertible_old` incomplete type when trait used.
template<>
struct is_copy_constructible<contract::unconvertible_old> : true_type {};
}
/** @endcond */
namespace boost { namespace contract {
template<typename T>
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.
*/
template<typename T>
class old_ptr { /* copyable (as *) */
public:
/** Pointed old value type. */
typedef T element_type;
/** Construct this object as a null old value pointer. */
old_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 and a
compile-time error if the pointed type is not copyable.
@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).
*/
T const& operator*() const {
BOOST_STATIC_ASSERT_MSG(
boost::is_copy_constructible<T>::value,
@@ -105,6 +145,13 @@ public:
return *ptr_;
}
/**
Access the pointed old value.
This will generate a compile-time error if the pointed type is not copyable.
@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).
*/
T const* operator->() const {
BOOST_STATIC_ASSERT_MSG(
boost::is_copy_constructible<T>::value,
@@ -113,8 +160,17 @@ public:
return ptr_.operator->();
}
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr<T>, !!ptr_)
#ifndef DOXYGEN
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr<T>, !!ptr_)
#else
/**
Safe-bool operator.
@return True if this pointer is not null, false otherwise.
*/
explicit operator bool() const;
#endif
/** @cond */
private:
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
explicit old_ptr(boost::shared_ptr<T const> ptr) :
@@ -125,33 +181,72 @@ private:
friend class convertible_old;
friend class old_ptr_noncopyable<T>;
/** @endcond */
};
// Similar to above, but does not statically assert copy constructible.
/**
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).
*/
template<typename T>
class old_ptr_noncopyable { /* copyable (as *) */
public:
/** Pointed old value type. */
typedef T element_type;
/** Construct this object as a null old value pointer. */
old_ptr_noncopyable() {}
// Required to assign to OLDOF (as OLDOF returns old_ptr for auto decl).
/**
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}.
@param other Copyable-only old value pointer.
*/
/* implicit */ old_ptr_noncopyable(old_ptr<T> const& other) :
ptr_(other.ptr_) {}
/* only const access (contracts should not change old values) */
// 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).
@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).
*/
T const& operator*() const {
BOOST_CONTRACT_DETAIL_DEBUG(ptr_);
return *ptr_;
}
/**
Access the pointed old value.
(This will not generate a compile-time error if the pointed type is not
copyable.)
@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).
*/
T const* operator->() const {
return ptr_.operator->();
}
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_noncopyable<T>, !!ptr_)
#ifndef DOXYGEN
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr_noncopyable<T>, !!ptr_)
#else
/**
Safe-bool operator.
@return True if this pointer is not null, false otherwise.
*/
explicit operator bool() const;
#endif
/** @cond */
private:
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
explicit old_ptr_noncopyable(boost::shared_ptr<T const> ptr) :
@@ -161,12 +256,26 @@ private:
boost::shared_ptr<T const> ptr_;
friend class convertible_old;
/** @endcond */
};
/**
Internally hold old value copies.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
class unconvertible_old { // 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}).
@tparam T Old value type.
@param old_value Old value to be copied.
*/
template<typename T>
/* implicit */ unconvertible_old(
T const& old_value,
@@ -174,15 +283,24 @@ public:
)
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
: ptr_(boost::make_shared<T>(old_value)) // The one single T's copy.
#endif // Else, null ptr_ (so not copy of T).
#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.
@tparam T Old value type.
@param old_value Old value (that will not be copied in this case).
*/
template<typename T>
/* implicit */ unconvertible_old(
T const&,
T const& old_value,
typename boost::disable_if<boost::is_copy_constructible<T> >::type* = 0
) {} // Null ptr_ (so no copy of T).
) {} // Leave ptr_ null (and no copy of T).
/** @cond */
private:
explicit unconvertible_old() {}
@@ -193,22 +311,38 @@ private:
friend class convertible_old;
friend unconvertible_old null_old();
/** @endcond */
};
/**
Internally convert old value copies to old value pointers.
@see @RefSect{advanced_topics, Advanced Topics}.
*/
class convertible_old { // Copyable (as *).
public:
// Implicitly called by ctor init `old_ptr_noncopyable<T> old_x = ...`.
/**
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).
*/
template<typename T>
/* implicit */ operator old_ptr_noncopyable<T>() {
return ptr<old_ptr_noncopyable<T> >();
}
// Implicitly called by ctor init `old_ptr<T> old_x = ...`.
/**
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).
*/
template<typename T>
/* implicit */ operator old_ptr<T>() {
return ptr<old_ptr<T> >();
}
/** @cond */
private:
explicit convertible_old(virtual_* v, unconvertible_old const& old)
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
@@ -277,18 +411,43 @@ private:
friend convertible_old make_old(unconvertible_old const&);
friend convertible_old make_old(virtual_*, unconvertible_old const&);
/** @endcond */
};
/**
Make a null old value copy (i.e., the related old value pointer will be null).
@see @RefSect{advanced_topics, Advanced Topics}.
*/
unconvertible_old null_old() { return unconvertible_old(); }
/**
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}).
*/
convertible_old make_old(unconvertible_old const& old) {
return convertible_old(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}).
*/
convertible_old make_old(virtual_* v, unconvertible_old const& old) {
return convertible_old(v, old);
}
/**
Return true if and only if old values need to be copied (for non virtual and
not 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}.
*/
bool copy_old() {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
return !boost::contract::detail::check_guard::checking();
@@ -297,6 +456,14 @@ bool copy_old() {
#endif
}
/**
Return true if and only if old values need to be copied (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.
*/
bool copy_old(virtual_* v) {
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
if(!v) return !boost::contract::detail::check_guard::checking();

View File

@@ -7,18 +7,24 @@
// 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
Support contracts for overriding public functions.
*/
#include <boost/contract/detail/all_core_headers.hpp>
#include <boost/contract/detail/tvariadic.hpp>
#include <boost/preprocessor/cat.hpp>
/* PRIVATE */
#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
#include <boost/contract/detail/type_traits/introspection.hpp>
#include <boost/contract/detail/none.hpp>
#include <boost/contract/detail/name.hpp>
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_(z, arity, arity_compl, f) \
/* PRIVATE */
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_(z, \
arity, arity_compl, function_name) \
template< \
class BOOST_CONTRACT_DETAIL_NAME1(B), \
class BOOST_CONTRACT_DETAIL_NAME1(C) \
@@ -40,7 +46,7 @@
boost::contract::detail::none&) \
) { \
BOOST_CONTRACT_DETAIL_NAME1(obj)-> \
BOOST_CONTRACT_DETAIL_NAME1(B)::f( \
BOOST_CONTRACT_DETAIL_NAME1(B)::function_name( \
BOOST_CONTRACT_DETAIL_TVARIADIC_ARGS_Z(z, arity, \
BOOST_CONTRACT_DETAIL_NAME1(args)) \
BOOST_CONTRACT_DETAIL_TVARIADIC_COMMA(arity) \
@@ -49,38 +55,66 @@
}
#if BOOST_CONTRACT_DETAIL_TVARIADIC
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(f) \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_(1, ~, ~, f)
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(function_name) \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_(1, ~, ~, function_name)
#else
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/arithmetic/sub.hpp>
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(f) \
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(function_name) \
BOOST_PP_REPEAT(BOOST_PP_INC(BOOST_CONTRACT_MAX_ARGS), \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_ARITY_, f) \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_ARITY_, function_name) \
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_ARITY_(z, arity, f) \
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_ARITY_(z, arity, \
function_name) \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_(z, arity, \
BOOST_PP_SUB(BOOST_CONTRACT_MAX_ARGS, arity), f)
BOOST_PP_SUB(BOOST_CONTRACT_MAX_ARGS, arity), function_name)
#endif
/* PUBLIC */
/* PUBLIC */
#define BOOST_CONTRACT_NAMED_OVERRIDE(name, f) \
#define BOOST_CONTRACT_NAMED_OVERRIDE(override_name, function_name) \
struct name { \
BOOST_CONTRACT_DETAIL_INTROSPECTION_HAS_MEMBER_FUNCTION( \
BOOST_CONTRACT_DETAIL_NAME1(has_member_function), f) \
\
BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(f) \
BOOST_CONTRACT_DETAIL_NAME1(has_member_function), \
function_name \
) \
BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(function_name) \
};
#else
// Empty type (not actually used) just needed to compile user contract code.
#define BOOST_CONTRACT_NAMED_OVERRIDE(name, f) struct name {};
/**
Declare override type allowing to explicitly specify its name.
Declare 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.
@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
@RefSect{advanced_topics, Advanced Topics}).
*/
#define BOOST_CONTRACT_NAMED_OVERRIDE(override_name, function_name) \
struct name {}; /* empty type (not used) just to compile code */
#endif
/* PUBLIC */
#define BOOST_CONTRACT_OVERRIDE(f) \
BOOST_CONTRACT_NAMED_OVERRIDE(BOOST_PP_CAT(override_, f), f)
/**
Declare override type naming it <c>override_<e>function_name</e></c>.
Declare 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 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
@RefSect{advanced_topics, Advanced Topics}).
*/
#define BOOST_CONTRACT_OVERRIDE(function_name) \
BOOST_CONTRACT_NAMED_OVERRIDE(BOOST_PP_CAT(override_, function_name), \
function_name)
#if BOOST_CONTRACT_DETAIL_TVARIADIC
#include <boost/preprocessor/seq/for_each.hpp>
@@ -88,11 +122,23 @@
/* PRIVATE */
#define BOOST_CONTRACT_OVERRIDES_SEQ_(r, unused, f) \
BOOST_CONTRACT_OVERRIDE(f)
/** @cond */
#define BOOST_CONTRACT_OVERRIDES_SEQ_(r, unused, function_name) \
BOOST_CONTRACT_OVERRIDE(function_name)
/** @endcond */
/* PUBLIC */
/**
Declare multiple override types at once naming them <c>override_...</c>.
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}.
@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.
*/
#define BOOST_CONTRACT_OVERRIDES(...) \
BOOST_PP_SEQ_FOR_EACH(BOOST_CONTRACT_OVERRIDES_SEQ_, ~, \
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

View File

@@ -7,6 +7,12 @@
// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
/** @file
Program contracts for public member functions.
Different overloads are provided to handle static, virtual void/non-void, and
overriding void/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.
// TODO: Document that not using variadic templates (i.e., using pp meta-programming impl instead) does not increase compilation times (I measured this with the max_arg test program).
@@ -51,7 +57,20 @@ namespace boost { namespace contract {
// However, R is never specified, not even for virtual functions, when the
// return type is void (i.e., R always optional).
// For static public functions.
/**
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).
*/
template<class C>
set_precondition_old_postcondition<> public_function() {
#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
@@ -62,7 +81,22 @@ set_precondition_old_postcondition<> public_function() {
#endif
}
// For non-static, non-virtual, and non-overriding public functions.
/**
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).
*/
template<class C>
set_precondition_old_postcondition<> public_function(C* obj) {
#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
@@ -95,6 +129,8 @@ set_precondition_old_postcondition<> public_function(C* obj) {
#endif
}
/** @cond */
// To use within macro expansions instead of defined(...) (PRIVATE macro).
#ifdef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
#define BOOST_CONTRACT_PUBLIC_FUNCTIONS_ 0
@@ -158,8 +194,65 @@ set_precondition_old_postcondition<> public_function(C* obj) {
) \
}
BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 0)
BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 1)
/** @endcond */
#ifdef DOXYGEN
/**
Program contracts for virtual but 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}.
@param v The contracted virtual function extra trailing parameter of type
@RefClass{boost::contract::virtual_}<c>*</c> 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
@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).
*/
template<class C>
set_precondition_old_postcondition<> public_function(virtual_* v, C* obj);
/**
Program contracts for virtual but 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}.
@param v The contracted virtual function extra trailing parameter of type
@RefClass{boost::contract::virtual_}<c>*</c> 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
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
@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).
*/
template<typename R, class C>
set_precondition_old_postcondition<R> public_function(
virtual_* v, R& r, C* obj);
#else
BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 0)
BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 1)
#endif
/** @cond */
// For non-static, virtual, and overriding public functions (PRIVATE macro).
#define BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_OVERRIDE_Z_( \
@@ -234,7 +327,87 @@ BOOST_CONTRACT_PUBLIC_FUNCTION_VIRTUAL_NO_OVERRIDE_(/* has_result = */ 1)
) \
}
#if BOOST_CONTRACT_DETAIL_TVARIADIC
/** @endcond */
#ifdef DOXYGEN
/**
Program contracts for overriding (virtual or not) 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}.
@param v The contracted virtual function extra trailing parameter of type
@RefClass{boost::contract::virtual_}<c>*</c> 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
@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
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).
*/
template<class O, typename F, class C, typename... Args>
set_precondition_old_postcondition<> public_function(
virtual_* v, F f, C* obj, Args&... args);
/**
Program contracts for overriding (virtual or not) 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}.
@param v The contracted virtual function extra trailing parameter of type
@RefClass{boost::contract::virtual_}<c>*</c> 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
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
@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
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).
*/
template<class O, typename R, typename F, class C, typename... Args>
set_precondition_old_postcondition<R> public_function(
virtual_* v, R& r, F f, C* 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,