// 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 #include #include #include #include template class pushable { public: void invariant() const { BOOST_CONTRACT_ASSERT(capacity() <= max_size()); } virtual void push_back(T x, boost::contract::virtual_* v = 0) = 0; protected: virtual unsigned capacity() const = 0; virtual unsigned max_size() const = 0; }; template void pushable::push_back(T x, boost::contract::virtual_* v) { boost::contract::old_ptr old_capacity = BOOST_CONTRACT_OLDOF(v, capacity()); boost::contract::check c = boost::contract::public_function(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(capacity() < max_size()); }) .postcondition([&] { BOOST_CONTRACT_ASSERT(capacity() >= *old_capacity); }) ; assert(false); // Shall never execute this body. } struct has_size { virtual unsigned size() const = 0; }; struct has_empty { virtual bool empty() const = 0; }; class unique_chars : private boost::contract::constructor_precondition { public: void invariant() const { BOOST_CONTRACT_ASSERT(size() >= 0); } unique_chars(char from, char to) : boost::contract::constructor_precondition([&] { BOOST_CONTRACT_ASSERT(from <= to); }) { boost::contract::check c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(int(size()) == (to - from + 1)); }) ; for(char x = from; x <= to; ++x) vect_.push_back(x); } virtual ~unique_chars() { boost::contract::check c = boost::contract::destructor(this); } unsigned size() const { boost::contract::check c = boost::contract::public_function(this); return vect_.size(); } bool find(char x) const { bool result; boost::contract::check c = boost::contract::public_function(this) .postcondition([&] { if(size() == 0) BOOST_CONTRACT_ASSERT(!result); }) ; return result = std::find(vect_.begin(), vect_.end(), x) != vect_.end(); } virtual void push_back(char x, boost::contract::virtual_* v = 0) { boost::contract::old_ptr old_find = BOOST_CONTRACT_OLDOF(v, find(x)); boost::contract::old_ptr old_size = BOOST_CONTRACT_OLDOF(v, size()); boost::contract::check c = boost::contract::public_function(v, this) .precondition([&] { BOOST_CONTRACT_ASSERT(!find(x)); }) .postcondition([&] { if(!*old_find) { BOOST_CONTRACT_ASSERT(find(x)); BOOST_CONTRACT_ASSERT(size() == *old_size + 1); } }) ; vect_.push_back(x); } protected: unique_chars() {} std::vector const& vect() const { return vect_; } private: std::vector vect_; }; //[base_types_no_macro #include class chars : private boost::contract::constructor_precondition, public unique_chars, public virtual pushable, virtual protected has_size, private has_empty { public: // Program `base_types` without macros (list only public bases). typedef boost::mpl::vector > base_types; /* ... */ //] void invariant() const { BOOST_CONTRACT_ASSERT(empty() == (size() == 0)); } chars(char from, char to) : unique_chars(from, to) { boost::contract::check c = boost::contract::constructor(this); } chars(char const* const c_str) : boost::contract::constructor_precondition([&] { BOOST_CONTRACT_ASSERT(c_str[0] != '\0'); }) { boost::contract::check c = boost::contract::constructor(this); for(unsigned i = 0; c_str[i] != '\0'; ++i) push_back(c_str[i]); } void push_back(char x, boost::contract::virtual_* v = 0) /* override */ { boost::contract::old_ptr old_find = BOOST_CONTRACT_OLDOF(v, find(x)); boost::contract::old_ptr old_size = BOOST_CONTRACT_OLDOF(v, size()); boost::contract::check c = boost::contract::public_function< override_push_back>(v, &chars::push_back, this, x) .precondition([&] { BOOST_CONTRACT_ASSERT(find(x)); }) .postcondition([&] { if(*old_find) BOOST_CONTRACT_ASSERT(size() == *old_size); }) ; if(!find(x)) unique_chars::push_back(x); } BOOST_CONTRACT_OVERRIDE(push_back); bool empty() const { boost::contract::check c = boost::contract::public_function(this); return size() == 0; } unsigned size() const { return unique_chars::size(); } protected: unsigned max_size() const { return vect().max_size(); } unsigned capacity() const { return vect().capacity(); } }; int main() { chars s("abc"); assert(s.find('a')); assert(s.find('b')); assert(!s.find('x')); return 0; }