mirror of
https://github.com/boostorg/contract.git
synced 2026-02-27 04:52:22 +00:00
finished advanced topic section of docs
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
#include <boost/contract/override.hpp>
|
||||
#include <boost/contract/public_function.hpp>
|
||||
|
||||
// TODO: Add a test for all operators (member and non-member ones). In theory nothing special should be needed for operators... but test it. For member operators, test them with public_function virtual overrides.
|
||||
|
||||
// TODO: Document compile and run time performances (after creating specific tests to measure them).
|
||||
|
||||
// TODO: Add all copyright and licencing info (to all files, etc.).
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/type_traits/is_copy_constructible.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/preprocessor/control/expr_iif.hpp>
|
||||
#include <boost/preprocessor/config/config.hpp>
|
||||
|
||||
#if !BOOST_PP_VARIADICS
|
||||
@@ -53,7 +55,7 @@ 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() \
|
||||
))
|
||||
|
||||
|
||||
/* PUBLIC */
|
||||
|
||||
// NOTE: Leave this #defined the same regardless of ..._POSTCONDITIONS.
|
||||
@@ -68,6 +70,39 @@ BOOST_CONTRACT_ERROR_macro_OLDOF_requires_variadic_macros_otherwise_manually_pro
|
||||
|
||||
#endif // variadics
|
||||
|
||||
/* PRIVATE */
|
||||
|
||||
#ifdef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
#define BOOST_CONTRACT_OLD_POSTCONDITIONS_ 0
|
||||
#else
|
||||
#define BOOST_CONTRACT_OLD_POSTCONDITIONS_ 1
|
||||
#endif
|
||||
|
||||
// Used to avoid exposing entire shared_ptr API (e.g., client stealing
|
||||
// pointer ownership could break this library).
|
||||
#define BOOST_CONTRACT_OLD_PTR_DEF_(pointer_name, pointed_type) \
|
||||
public: \
|
||||
typedef pointed_type element_type; \
|
||||
\
|
||||
pointer_name() {} \
|
||||
\
|
||||
/* only const access (contracts should not change old values) */ \
|
||||
\
|
||||
pointed_type const* operator->() const { return ptr_.operator->(); } \
|
||||
\
|
||||
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(pointer_name<pointed_type>, \
|
||||
!!ptr_) \
|
||||
\
|
||||
private: \
|
||||
BOOST_PP_EXPR_IIF(BOOST_CONTRACT_OLD_POSTCONDITIONS_, \
|
||||
explicit pointer_name(boost::shared_ptr<pointed_type const> ptr) : \
|
||||
ptr_(ptr) {} \
|
||||
) \
|
||||
\
|
||||
boost::shared_ptr<pointed_type const> ptr_; \
|
||||
\
|
||||
friend class convertible_old;
|
||||
|
||||
/* CODE */
|
||||
|
||||
// Specialization because `unconvertible_old` incomplete type when trait used.
|
||||
@@ -82,32 +117,41 @@ namespace boost {
|
||||
|
||||
namespace boost { namespace contract {
|
||||
|
||||
// Used to avoid exposing entire shared_ptr API (e.g., client stealing
|
||||
// ownership of this pointer could break this lib).
|
||||
template<typename T>
|
||||
class old_ptr { // Copyable (as *).
|
||||
public:
|
||||
explicit old_ptr() {}
|
||||
class noncopyable_old_ptr;
|
||||
|
||||
// Only const access (because contracts should not change program state).
|
||||
|
||||
template<typename T>
|
||||
class old_ptr { /* copyable (as *) */
|
||||
BOOST_CONTRACT_OLD_PTR_DEF_(old_ptr, T)
|
||||
|
||||
public:
|
||||
T const& operator*() const {
|
||||
// Compiler error if old_ptr<T>::operator* and non-copyable T.
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
boost::is_copy_constructible<T>::value,
|
||||
"old_ptr<T> requires T copy constructor, otherwise use noncopyable_old_ptr<T>"
|
||||
);
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(ptr_);
|
||||
return *ptr_;
|
||||
}
|
||||
|
||||
T const* operator->() const { return ptr_.operator->(); }
|
||||
friend class noncopyable_old_ptr<T>;
|
||||
};
|
||||
|
||||
BOOST_CONTRACT_DETAIL_OPERATOR_SAFE_BOOL(old_ptr<T>, !!ptr_)
|
||||
template<typename T>
|
||||
class noncopyable_old_ptr { /* copyable (as *) */
|
||||
BOOST_CONTRACT_OLD_PTR_DEF_(noncopyable_old_ptr, T)
|
||||
|
||||
public:
|
||||
// Required to assign to OLDOF (as OLDOF returns old_ptr for auto decl).
|
||||
/* implicit */ noncopyable_old_ptr(old_ptr<T> const& other) :
|
||||
ptr_(other.ptr_) {}
|
||||
|
||||
private:
|
||||
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
explicit old_ptr(boost::shared_ptr<T const> ptr) : ptr_(ptr) {}
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<T const> ptr_;
|
||||
|
||||
friend class convertible_old;
|
||||
T const& operator*() const {
|
||||
// No static assert is_copy_constructible so T can be non-copyable here.
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(ptr_);
|
||||
return *ptr_;
|
||||
}
|
||||
};
|
||||
|
||||
class unconvertible_old { // Copyable (as *).
|
||||
@@ -144,21 +188,42 @@ private:
|
||||
|
||||
class convertible_old { // Copyable (as *).
|
||||
public:
|
||||
// Implicitly called by constructor init `old_ptr<T> old_x = ...`.
|
||||
// Implicitly called by ctor init `noncopyable_old_ptr<T> old_x = ...`.
|
||||
template<typename T>
|
||||
/* implicit */ operator noncopyable_old_ptr<T>() {
|
||||
return ptr<noncopyable_old_ptr<T> >();
|
||||
}
|
||||
|
||||
// Implicitly called by ctor init `old_ptr<T> old_x = ...`.
|
||||
template<typename T>
|
||||
/* implicit */ operator old_ptr<T>() {
|
||||
return ptr<old_ptr<T> >();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit convertible_old(virtual_* v, unconvertible_old const& old)
|
||||
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
if(!boost::is_copy_constructible<T>::value) {
|
||||
: v_(v), ptr_(old.ptr_)
|
||||
#endif
|
||||
{}
|
||||
|
||||
template<typename Ptr>
|
||||
Ptr ptr() {
|
||||
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
if(!boost::is_copy_constructible<
|
||||
typename Ptr::element_type>::value) {
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(!ptr_); // Non-copyable so no old...
|
||||
return old_ptr<T>(); // ...and return null.
|
||||
return Ptr(); // ...and return null.
|
||||
} else if(!v_ && boost::contract::detail::check_guard::checking()) {
|
||||
// Return null shared ptr (see after if statement).
|
||||
} else if(!v_) {
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(ptr_);
|
||||
boost::shared_ptr<T const> old =
|
||||
boost::static_pointer_cast<T const>(ptr_);
|
||||
boost::shared_ptr<typename Ptr::element_type const> old =
|
||||
boost::static_pointer_cast<
|
||||
typename Ptr::element_type const>(ptr_)
|
||||
;
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(old);
|
||||
return old_ptr<T>(old);
|
||||
return Ptr(old);
|
||||
} else if(v_->action_ == boost::contract::virtual_::push_old_init ||
|
||||
v_->action_ == boost::contract::virtual_::push_old_copy) {
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(ptr_);
|
||||
@@ -167,7 +232,7 @@ public:
|
||||
} else {
|
||||
v_->old_copies_.push(ptr_);
|
||||
}
|
||||
return old_ptr<T>();
|
||||
return Ptr();
|
||||
} else if(v_->action_ == boost::contract::virtual_::pop_old_init ||
|
||||
v_->action_ == boost::contract::virtual_::pop_old_copy) {
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(!ptr_);
|
||||
@@ -183,23 +248,18 @@ public:
|
||||
} else {
|
||||
v_->old_copies_.pop();
|
||||
}
|
||||
boost::shared_ptr<T const> old =
|
||||
boost::static_pointer_cast<T const>(ptr);
|
||||
boost::shared_ptr<typename Ptr::element_type const> old =
|
||||
boost::static_pointer_cast<
|
||||
typename Ptr::element_type const>(ptr)
|
||||
;
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(old);
|
||||
return old_ptr<T>(old);
|
||||
return Ptr(old);
|
||||
}
|
||||
BOOST_CONTRACT_DETAIL_DEBUG(!ptr_);
|
||||
#endif
|
||||
return old_ptr<T>();
|
||||
return Ptr();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit convertible_old(virtual_* v, unconvertible_old const& old)
|
||||
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
: v_(v), ptr_(old.ptr_)
|
||||
#endif
|
||||
{}
|
||||
|
||||
#ifndef BOOST_CONTRACT_NO_POSTCONDITIONS
|
||||
virtual_* v_;
|
||||
boost::shared_ptr<void> ptr_;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
|
||||
|
||||
#include <boost/contract/detail/all_core_headers.hpp>
|
||||
#include <boost/contract/detail/tvariadic.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
|
||||
/* PRIVATE */
|
||||
@@ -15,7 +16,6 @@
|
||||
#ifndef BOOST_CONTRACT_NO_PUBLIC_FUNCTIONS
|
||||
#include <boost/contract/detail/type_traits/introspection.hpp>
|
||||
#include <boost/contract/detail/none.hpp>
|
||||
#include <boost/contract/detail/tvariadic.hpp>
|
||||
#include <boost/contract/detail/name.hpp>
|
||||
|
||||
#define BOOST_CONTRACT_OVERRIDE_CALL_BASE_(z, arity, arity_compl, f) \
|
||||
@@ -67,20 +67,39 @@
|
||||
|
||||
/* PUBLIC */
|
||||
|
||||
#define BOOST_CONTRACT_OVERRIDE_TRAIT(trait, f) \
|
||||
struct trait { \
|
||||
#define BOOST_CONTRACT_NAMED_OVERRIDE(name, f) \
|
||||
struct name { \
|
||||
BOOST_CONTRACT_DETAIL_INTROSPECTION_HAS_MEMBER_FUNCTION( \
|
||||
BOOST_CONTRACT_DETAIL_NAME1(has_member_function), f) \
|
||||
\
|
||||
BOOST_CONTRACT_OVERRIDE_CALL_BASE_DECL_(f) \
|
||||
};
|
||||
#else
|
||||
#define BOOST_CONTRACT_OVERRIDE_TRAIT(trait, f) \
|
||||
struct trait {}; /* empty trait type (won't be actually used) */
|
||||
// Empty type (not actually used) just needed to compile user contract code.
|
||||
#define BOOST_CONTRACT_NAMED_OVERRIDE(name, f) struct name {};
|
||||
#endif
|
||||
|
||||
#define BOOST_CONTRACT_OVERRIDE(f) \
|
||||
BOOST_CONTRACT_OVERRIDE_TRAIT(BOOST_PP_CAT(override_, f), f)
|
||||
BOOST_CONTRACT_NAMED_OVERRIDE(BOOST_PP_CAT(override_, f), f)
|
||||
|
||||
#if BOOST_CONTRACT_DETAIL_TVARIADIC
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <boost/preprocessor/variadic/to_seq.hpp>
|
||||
|
||||
/* PRIVATE */
|
||||
|
||||
#define BOOST_CONTRACT_OVERRIDES_SEQ_(r, unused, f) \
|
||||
BOOST_CONTRACT_OVERRIDE(f)
|
||||
|
||||
/* PUBLIC */
|
||||
|
||||
#define BOOST_CONTRACT_OVERRIDES(...) \
|
||||
BOOST_PP_SEQ_FOR_EACH(BOOST_CONTRACT_OVERRIDES_SEQ_, ~, \
|
||||
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
|
||||
#else
|
||||
#define BOOST_CONTRACT_OVERRIDES \
|
||||
BOOST_CONTRACT_ERROR_macro_OVERRIDES_requires_variadic_macros_otherwise_manually_repeat_OVERRIDE_macro
|
||||
#endif
|
||||
|
||||
#endif // #include guard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user