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 <boost/config.hpp> 9 #include <cassert> 10 11 #ifdef BOOST_GCC // G++ does not support static union members yet. 12 int instances_ = 0; 13 #endif 14 15 //[union 16 union positive { 17 public: static_invariant()18 static void static_invariant() { // Static class invariants (as usual). 19 BOOST_CONTRACT_ASSERT(instances() >= 0); 20 } 21 invariant() const22 void invariant() const { // Class invariants (as usual). 23 BOOST_CONTRACT_ASSERT(i_ > 0); 24 BOOST_CONTRACT_ASSERT(d_ > 0); 25 } 26 27 // Contracts for constructor, as usual but... positive(int x)28 explicit positive(int x) : d_(0) { 29 // ...unions cannot have bases so constructor preconditions here. 30 boost::contract::constructor_precondition<positive> pre([&] { 31 BOOST_CONTRACT_ASSERT(x > 0); 32 }); 33 boost::contract::old_ptr<int> old_instances = 34 BOOST_CONTRACT_OLDOF(instances()); 35 boost::contract::check c = boost::contract::constructor(this) 36 .postcondition([&] { 37 { int y; get(y); BOOST_CONTRACT_ASSERT(y == x); } 38 BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); 39 }) 40 ; 41 42 i_ = x; 43 ++instances_; 44 } 45 46 // Contracts for destructor (as usual). ~positive()47 ~positive() { 48 boost::contract::old_ptr<int> old_instances = 49 BOOST_CONTRACT_OLDOF(instances()); 50 boost::contract::check c = boost::contract::destructor(this) 51 .postcondition([&] { 52 BOOST_CONTRACT_ASSERT(instances() == *old_instances - 1); 53 }) 54 ; 55 56 --instances_; 57 } 58 59 // Contracts for public function (as usual, but no virtual or override). get(int & x) const60 void get(int& x) const { 61 boost::contract::check c = boost::contract::public_function(this) 62 .postcondition([&] { 63 BOOST_CONTRACT_ASSERT(x > 0); 64 }) 65 ; 66 67 x = i_; 68 } 69 70 // Contracts for static public function (as usual). instances()71 static int instances() { 72 boost::contract::check c = boost::contract::public_function<positive>(); 73 return instances_; 74 } 75 76 private: 77 int i_; 78 double d_; 79 80 /* ... */ 81 //] 82 83 public: positive(double x)84 explicit positive(double x) : d_(0) { 85 // Unions cannot have bases so constructor preconditions here. 86 boost::contract::constructor_precondition<positive> pre([&] { 87 BOOST_CONTRACT_ASSERT(x > 0); 88 }); 89 boost::contract::old_ptr<int> old_instances = 90 BOOST_CONTRACT_OLDOF(instances()); 91 boost::contract::check c = boost::contract::constructor(this) 92 .postcondition([&] { 93 { double y; get(y); BOOST_CONTRACT_ASSERT(y == x); } 94 BOOST_CONTRACT_ASSERT(instances() == *old_instances + 1); 95 }) 96 ; 97 98 d_ = x; 99 ++instances_; 100 } 101 get(double & x) const102 void get(double& x) const { 103 boost::contract::check c = boost::contract::public_function(this) 104 .postcondition([&] { 105 BOOST_CONTRACT_ASSERT(x > 0); 106 }) 107 ; 108 109 x = d_; 110 } 111 112 #ifndef BOOST_GCC // G++ does not support static union members yet. 113 static int instances_; 114 #endif 115 }; 116 117 #ifndef BOOST_GCC // G++ does not support static union members yet. 118 int positive::instances_ = 0; 119 #endif 120 main()121int main() { 122 { 123 positive p(123); 124 assert(p.instances() == 1); 125 { int y = -456; p.get(y); assert(y == 123); } 126 127 positive q(1.23); 128 assert(q.instances() == 2); 129 { double y = -4.56; q.get(y); assert(y == 1.23); } 130 } 131 assert(positive::instances() == 0); 132 return 0; 133 } 134 135