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 // Test specializations of old value copy type traits. 8 9 #include <boost/contract/old.hpp> 10 #include <boost/type_traits.hpp> 11 #include <boost/noncopyable.hpp> 12 #include <boost/detail/lightweight_test.hpp> 13 #include <cassert> 14 15 template<typename T> f(T & x)16void f(T& x) { 17 // No OLDOF here so C++11 not required for this test. 18 boost::contract::old_ptr_if_copyable<T> old_x = boost::contract::make_old( 19 boost::contract::copy_old() ? x : boost::contract::null_old()); 20 } 21 22 // Test copyable type but... 23 struct w { ww24 w() {} ww25 w(w const&) { BOOST_TEST(false); } // Test this doesn't get copied. 26 }; 27 28 // ...never copy old values for type `w` (because its copy is too expensive). 29 namespace boost { namespace contract { 30 template<> 31 struct is_old_value_copyable<w> : boost::false_type {}; 32 } } // namespace 33 34 // Test non-copyable type but... 35 struct p : private boost::noncopyable { // Non-copyable via Boost. 36 static bool copied; pp37 p() : num_(new int(0)) {} ~pp38 ~p() { delete num_; } 39 private: 40 int* num_; 41 friend struct boost::contract::old_value_copy<p>; 42 }; 43 bool p::copied = false; 44 45 // ...still copy old values for type `p` (using a deep copy). 46 namespace boost { namespace contract { 47 template<> 48 struct old_value_copy<p> { old_value_copyboost::contract::old_value_copy49 explicit old_value_copy(p const& old) { 50 *old_.num_ = *old.num_; // Deep copy pointed value. 51 p::copied = true; 52 } 53 oldboost::contract::old_value_copy54 p const& old() const { return old_; } 55 56 private: 57 p old_; 58 }; 59 60 template<> 61 struct is_old_value_copyable<p> : boost::true_type {}; 62 } } // namespace 63 64 // Non-copyable type so... 65 struct n { nn66 n() {} 67 private: 68 n(n const&); // Non-copyable (but not via Boost). 69 }; 70 71 // ...specialize `boost::is_copy_constructible` (no need for this on C++11). 72 namespace boost { namespace contract { 73 template<> 74 struct is_old_value_copyable<n> : boost::false_type {}; 75 } } // namespace 76 main()77int main() { 78 // NOTE: No test::detail::counter below because that is for copyable types. 79 80 { 81 int x; // Test has copy ctor so copy olds. 82 f(x); 83 } 84 85 { 86 w x; // Test has copy ctor but never copy olds (see TEST(...) above). 87 f(x); 88 } 89 90 p::copied = false; 91 { 92 p x; // Test no copy ctor but still old copies. 93 f(x); 94 } 95 #ifndef BOOST_CONTRACT_NO_OLDS 96 BOOST_TEST(p::copied); 97 #else 98 BOOST_TEST(!p::copied); 99 #endif 100 101 { 102 n x; // Test no copy ctor so no old copies. 103 f(x); 104 } 105 106 return boost::report_errors(); 107 } 108 109