copyable_traits.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. // Copyright (C) 2008-2018 Lorenzo Caminiti
  2. // Distributed under the Boost Software License, Version 1.0 (see accompanying
  3. // file LICENSE_1_0.txt or a copy at http://www.boost.org/LICENSE_1_0.txt).
  4. // See: http://www.boost.org/doc/libs/release/libs/contract/doc/html/index.html
  5. // Test specializations of old value copy type traits.
  6. #include <boost/contract/old.hpp>
  7. #include <boost/type_traits.hpp>
  8. #include <boost/noncopyable.hpp>
  9. #include <boost/detail/lightweight_test.hpp>
  10. #include <cassert>
  11. template<typename T>
  12. void f(T& x) {
  13. // No OLDOF here so C++11 not required for this test.
  14. boost::contract::old_ptr_if_copyable<T> old_x = boost::contract::make_old(
  15. boost::contract::copy_old() ? x : boost::contract::null_old());
  16. }
  17. // Test copyable type but...
  18. struct w {
  19. w() {}
  20. w(w const&) { BOOST_TEST(false); } // Test this doesn't get copied.
  21. };
  22. // ...never copy old values for type `w` (because its copy is too expensive).
  23. namespace boost { namespace contract {
  24. template<>
  25. struct is_old_value_copyable<w> : boost::false_type {};
  26. } } // namespace
  27. // Test non-copyable type but...
  28. struct p : private boost::noncopyable { // Non-copyable via Boost.
  29. static bool copied;
  30. p() : num_(new int(0)) {}
  31. ~p() { delete num_; }
  32. private:
  33. int* num_;
  34. friend struct boost::contract::old_value_copy<p>;
  35. };
  36. bool p::copied = false;
  37. // ...still copy old values for type `p` (using a deep copy).
  38. namespace boost { namespace contract {
  39. template<>
  40. struct old_value_copy<p> {
  41. explicit old_value_copy(p const& old) {
  42. *old_.num_ = *old.num_; // Deep copy pointed value.
  43. p::copied = true;
  44. }
  45. p const& old() const { return old_; }
  46. private:
  47. p old_;
  48. };
  49. template<>
  50. struct is_old_value_copyable<p> : boost::true_type {};
  51. } } // namespace
  52. // Non-copyable type so...
  53. struct n {
  54. n() {}
  55. private:
  56. n(n const&); // Non-copyable (but not via Boost).
  57. };
  58. // ...specialize `boost::is_copy_constructible` (no need for this on C++11).
  59. namespace boost { namespace contract {
  60. template<>
  61. struct is_old_value_copyable<n> : boost::false_type {};
  62. } } // namespace
  63. int main() {
  64. // NOTE: No test::detail::counter below because that is for copyable types.
  65. {
  66. int x; // Test has copy ctor so copy olds.
  67. f(x);
  68. }
  69. {
  70. w x; // Test has copy ctor but never copy olds (see TEST(...) above).
  71. f(x);
  72. }
  73. p::copied = false;
  74. {
  75. p x; // Test no copy ctor but still old copies.
  76. f(x);
  77. }
  78. #ifndef BOOST_CONTRACT_NO_OLDS
  79. BOOST_TEST(p::copied);
  80. #else
  81. BOOST_TEST(!p::copied);
  82. #endif
  83. {
  84. n x; // Test no copy ctor so no old copies.
  85. f(x);
  86. }
  87. return boost::report_errors();
  88. }