summaryrefslogtreecommitdiff
path: root/boost/contract/detail/condition/cond_base.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/contract/detail/condition/cond_base.hpp')
-rw-r--r--boost/contract/detail/condition/cond_base.hpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/boost/contract/detail/condition/cond_base.hpp b/boost/contract/detail/condition/cond_base.hpp
new file mode 100644
index 0000000000..c3f4090461
--- /dev/null
+++ b/boost/contract/detail/condition/cond_base.hpp
@@ -0,0 +1,153 @@
+
+#ifndef BOOST_CONTRACT_DETAIL_COND_BASE_HPP_
+#define BOOST_CONTRACT_DETAIL_COND_BASE_HPP_
+
+// Copyright (C) 2008-2018 Lorenzo Caminiti
+// Distributed under the Boost Software License, Version 1.0 (see accompanying
+// file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
+// See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
+
+// NOTE: It seemed not possible to implement this library without inheritance
+// here because some sort of base type needs to be used to hold contract objects
+// in instances of boost::contract::check while polymorphically calling
+// init and destructor functions to check contracts at entry and exit. This
+// could be possible without inheritance only if boost::contract::check was made
+// a template type but that would complicate user code. In any case, early
+// experimentation with removing this base class and its virtual methods did not
+// seem to reduce compilation and/or run time.
+
+#include <boost/contract/core/exception.hpp>
+#include <boost/contract/core/config.hpp>
+#if !defined(BOOST_CONTRACT_NO_PRECONDITIONS) || \
+ !defined(BOOST_CONTRACT_NO_OLDS) || \
+ !defined(BOOST_CONTRACT_NO_EXEPTS)
+ #include <boost/function.hpp>
+#endif
+#include <boost/noncopyable.hpp>
+#ifndef BOOST_CONTRACT_ON_MISSING_CHECK_DECL
+ #include <boost/assert.hpp>
+#endif
+#include <boost/config.hpp>
+
+namespace boost { namespace contract { namespace detail {
+
+class cond_base : // Base to hold all contract objects for RAII.
+ private boost::noncopyable // Avoid copying possible user's ftor captures.
+{
+public:
+ explicit cond_base(boost::contract::from from) :
+ BOOST_CONTRACT_ERROR_missing_check_object_declaration(false)
+ , init_asserted_(false)
+ #ifndef BOOST_CONTRACT_NO_CONDITIONS
+ , from_(from)
+ , failed_(false)
+ #endif
+ {}
+
+ // Can override for checking on exit, but should call assert_initialized().
+ virtual ~cond_base() BOOST_NOEXCEPT_IF(false) {
+ // Catch error (but later) even if overrides miss assert_initialized().
+ if(!init_asserted_) assert_initialized();
+ }
+
+ void initialize() { // Must be called by owner ctor (i.e., check class).
+ BOOST_CONTRACT_ERROR_missing_check_object_declaration = true;
+ this->init(); // So all inits (pre, old, post) done after owner decl.
+ }
+
+ #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
+ template<typename F>
+ void set_pre(F const& f) { pre_ = f; }
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_OLDS
+ template<typename F>
+ void set_old(F const& f) { old_ = f; }
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_EXCEPTS
+ template<typename F>
+ void set_except(F const& f) { except_ = f; }
+ #endif
+
+protected:
+ void assert_initialized() { // Derived dtors must assert this at entry.
+ init_asserted_ = true;
+ #ifdef BOOST_CONTRACT_ON_MISSING_CHECK_DECL
+ if(!BOOST_CONTRACT_ERROR_missing_check_object_declaration) {
+ BOOST_CONTRACT_ON_MISSING_CHECK_DECL;
+ }
+ #else
+ // Cannot use a macro instead of this ERROR_... directly here
+ // because assert will not expand it in the error message.
+ BOOST_ASSERT(BOOST_CONTRACT_ERROR_missing_check_object_declaration);
+ #endif
+ }
+
+ virtual void init() {} // Override for checking on entry.
+
+ // Return true if actually checked calling user ftor.
+ #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
+ bool check_pre(bool throw_on_failure = false) {
+ if(failed()) return true;
+ try { if(pre_) pre_(); else return false; }
+ catch(...) {
+ // Subcontracted pre must throw on failure (instead of
+ // calling failure handler) so to be checked in logic-or.
+ if(throw_on_failure) throw;
+ fail(&boost::contract::precondition_failure);
+ }
+ return true;
+ }
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_OLDS
+ void copy_old() {
+ if(failed()) return;
+ try { if(old_) old_(); }
+ catch(...) { fail(&boost::contract::old_failure); }
+ }
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_EXCEPTS
+ void check_except() {
+ if(failed()) return;
+ try { if(except_) except_(); }
+ catch(...) { fail(&boost::contract::except_failure); }
+ }
+ #endif
+
+ #ifndef BOOST_CONTRACT_NO_CONDITIONS
+ void fail(void (*h)(boost::contract::from)) {
+ failed(true);
+ if(h) h(from_);
+ }
+
+ // Virtual so overriding pub func can use virtual_::failed_ instead.
+ virtual bool failed() const { return failed_; }
+ virtual void failed(bool value) { failed_ = value; }
+ #endif
+
+private:
+ bool BOOST_CONTRACT_ERROR_missing_check_object_declaration;
+ bool init_asserted_; // Avoid throwing twice from dtors (undef behavior).
+ #ifndef BOOST_CONTRACT_NO_CONDITIONS
+ boost::contract::from from_;
+ bool failed_;
+ #endif
+ // Following use Boost.Function to handle also lambdas, binds, etc.
+ #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
+ boost::function<void ()> pre_;
+ #endif
+ #ifndef BOOST_CONTRACT_NO_OLDS
+ boost::function<void ()> old_;
+ #endif
+ #ifndef BOOST_CONTRACT_NO_EXCEPTS
+ boost::function<void ()> except_;
+ #endif
+};
+
+} } } // namespace
+
+#endif // #include guard
+