finished advanced topic section of docs

This commit is contained in:
Lorenzo Caminiti
2016-05-05 16:14:37 -07:00
parent b18ef53e22
commit 0c8a75df83
30 changed files with 1472 additions and 616 deletions

View File

@@ -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.).

View File

@@ -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_;

View File

@@ -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