2 // Copyright (C) 2008-2018 Lorenzo Caminiti
3 // Distributed under the Boost Software License, Version 1.0 (see accompanying
4 // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
5 // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
7 #include <boost/contract.hpp>
12 //[throw_on_failure_class_begin
13 struct too_large_error {};
15 template<unsigned MaxSize>
17 #define BASES private boost::contract::constructor_precondition<cstring< \
23 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
26 //[throw_on_failure_ctor
28 /* implicit */ cstring(char const* chars) :
29 boost::contract::constructor_precondition<cstring>([&] {
30 BOOST_CONTRACT_ASSERT(chars); // Throw `assertion_failure`.
31 // Or, throw user-defined exception.
32 if(std::strlen(chars) > MaxSize) throw too_large_error();
36 boost::contract::check c = boost::contract::constructor(this)
38 BOOST_CONTRACT_ASSERT(size() == std::strlen(chars));
42 size_ = std::strlen(chars);
43 for(unsigned i = 0; i < size_; ++i) chars_[i] = chars[i];
47 //[throw_on_failure_dtor
49 void invariant() const {
50 if(size() > MaxSize) throw too_large_error(); // Throw user-defined ex.
51 BOOST_CONTRACT_ASSERT(chars_); // Or, throw `assertion_failure`.
52 BOOST_CONTRACT_ASSERT(chars_[size()] == '\0');
55 ~cstring() noexcept { // Exception specifiers apply to contract code.
57 boost::contract::check c = boost::contract::destructor(this);
61 unsigned size() const {
63 boost::contract::check c = boost::contract::public_function(this);
68 char chars_[MaxSize + 1];
70 //[throw_on_failure_class_end
75 void bad_throwing_handler() { // For docs only (not actually used here).
76 //[throw_on_failure_bad_handler
79 // Warning... might cause destructors to throw (unless declared noexcept).
80 boost::contract::set_invariant_failure(
81 [] (boost::contract::from) {
82 throw; // Throw no matter if from destructor, etc.
90 //[throw_on_failure_handlers
92 boost::contract::set_precondition_failure(
93 boost::contract::set_postcondition_failure(
94 boost::contract::set_invariant_failure(
95 boost::contract::set_old_failure(
96 [] (boost::contract::from where) {
97 if(where == boost::contract::from_destructor) {
98 // Shall not throw from C++ destructors.
99 std::clog << "ignored destructor contract failure" << std::endl;
100 } else throw; // Re-throw (assertion_failure, user-defined, etc.).
103 boost::contract::set_except_failure(
104 [] (boost::contract::from) {
105 // Already an active exception so shall not throw another...
106 std::clog << "ignored exception guarantee failure" << std::endl;
109 boost::contract::set_check_failure(
111 // But now CHECK shall not be used in destructor implementations.
112 throw; // Re-throw (assertion_failure, user-defined, etc.).
121 assert(s.size() == 3);
124 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS
125 // These failures properly handled only when preconditions checked.
131 } catch(boost::contract::assertion_failure const& error) {
133 std::clog << "ignored: " << error.what() << std::endl;
134 } catch(...) { assert(false); }
137 cstring<3> s("abcd");
139 } catch(too_large_error const&) {} // OK (expected).
140 catch(...) { assert(false); }