1 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 6 7 #include <boost/contract.hpp> 8 #include <iostream> 9 #include <cstring> 10 #include <cassert> 11 12 //[throw_on_failure_class_begin 13 struct too_large_error {}; 14 15 template<unsigned MaxSize> 16 class cstring 17 #define BASES private boost::contract::constructor_precondition<cstring< \ 18 MaxSize> > 19 : BASES 20 { 21 //] 22 public: 23 typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; 24 #undef BASES 25 26 //[throw_on_failure_ctor 27 public: cstring(char const * chars)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(); 33 }) 34 { 35 //] 36 boost::contract::check c = boost::contract::constructor(this) __anon6f0d9b110202null37 .postcondition([&] { 38 BOOST_CONTRACT_ASSERT(size() == std::strlen(chars)); 39 }) 40 ; 41 42 size_ = std::strlen(chars); 43 for(unsigned i = 0; i < size_; ++i) chars_[i] = chars[i]; 44 chars_[size_] = '\0'; 45 } 46 47 //[throw_on_failure_dtor 48 public: invariant() const49 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'); 53 } 54 ~cstring()55 ~cstring() noexcept { // Exception specifiers apply to contract code. 56 // Check invariants. 57 boost::contract::check c = boost::contract::destructor(this); 58 } 59 //] 60 size() const61 unsigned size() const { 62 // Check invariants. 63 boost::contract::check c = boost::contract::public_function(this); 64 return size_; 65 } 66 67 private: 68 char chars_[MaxSize + 1]; 69 unsigned size_; 70 //[throw_on_failure_class_end 71 /* ... */ 72 }; 73 //] 74 bad_throwing_handler()75void bad_throwing_handler() { // For docs only (not actually used here). 76 //[throw_on_failure_bad_handler 77 /* ... */ 78 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. 83 } 84 ); 85 86 /* ... */ 87 //] 88 } 89 90 //[throw_on_failure_handlers main()91int main() { 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.). 101 } 102 )))); 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; 107 } 108 ); 109 boost::contract::set_check_failure( 110 [] { 111 // But now CHECK shall not be used in destructor implementations. 112 throw; // Re-throw (assertion_failure, user-defined, etc.). 113 } 114 ); 115 116 /* ... */ 117 //] 118 119 { 120 cstring<3> s("abc"); 121 assert(s.size() == 3); 122 } 123 124 #ifndef BOOST_CONTRACT_NO_PRECONDITIONS 125 // These failures properly handled only when preconditions checked. 126 127 try { 128 char* c = 0; 129 cstring<3> s(c); 130 assert(false); 131 } catch(boost::contract::assertion_failure const& error) { 132 // OK (expected). 133 std::clog << "ignored: " << error.what() << std::endl; 134 } catch(...) { assert(false); } 135 136 try { 137 cstring<3> s("abcd"); 138 assert(false); 139 } catch(too_large_error const&) {} // OK (expected). 140 catch(...) { assert(false); } 141 #endif 142 143 return 0; 144 } 145 146