]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/contract/example/features/throw_on_failure.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / contract / example / features / throw_on_failure.cpp
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:
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)
37 .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:
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');
53 }
54
55 ~cstring() noexcept { // Exception specifiers apply to contract code.
56 // Check invariants.
57 boost::contract::check c = boost::contract::destructor(this);
58 }
59 //]
60
61 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
75 void 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
91 int 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