if_constexpr.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // Copyright (C) 2008-2019 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. #include <boost/contract.hpp>
  6. #include <boost/type_traits/has_equal_to.hpp>
  7. #include <utility>
  8. #include <cassert>
  9. //[if_constexpr
  10. template<typename T>
  11. void swap(T& x, T& y) {
  12. constexpr bool b = boost::contract::is_old_value_copyable<T>::value &&
  13. boost::has_equal_to<T>::value;
  14. boost::contract::old_ptr<T> old_x, old_y;
  15. if constexpr(b) { // Contract requires copyable T...
  16. old_x = BOOST_CONTRACT_OLDOF(x);
  17. old_y = BOOST_CONTRACT_OLDOF(y);
  18. }
  19. boost::contract::check c = boost::contract::function()
  20. .postcondition([&] {
  21. if constexpr(b) { // ... and T with `==`...
  22. BOOST_CONTRACT_ASSERT(x == *old_y);
  23. BOOST_CONTRACT_ASSERT(y == *old_x);
  24. }
  25. })
  26. ;
  27. T t = std::move(x); // ...but body only requires movable T.
  28. x = std::move(y);
  29. y = std::move(t);
  30. }
  31. //]
  32. struct i { // Non-copyable but has operator==.
  33. explicit i(int n) : n_(n) {}
  34. i(i const&) = delete; // Non-copyable.
  35. i& operator=(i const&) = delete;
  36. i(i const&& o) : n_(o.n_) {}
  37. i& operator=(i const&& o) { n_ = o.n_; return *this; }
  38. friend bool operator==(i const& l, i const& r) { // Operator==.
  39. return l.n_ == r.n_;
  40. }
  41. private:
  42. int n_;
  43. };
  44. struct j { // Copyable but no operator==.
  45. explicit j(int n) : n_(n) {}
  46. j(j const& o) : n_(o.n_) {} // Copyable.
  47. j& operator=(j const& o) { n_ = o.n_; return *this; }
  48. j(j const&& o) : n_(o.n_) {}
  49. j& operator=(j const&& o) { n_ = o.n_; return *this; }
  50. // No operator==.
  51. private:
  52. int n_;
  53. };
  54. struct k { // Non-copyable and no operator==.
  55. explicit k(int n) : n_(n) {}
  56. k(k const&) = delete; // Non-copyable.
  57. k& operator=(k const&) = delete;
  58. k(k const&& o) : n_(o.n_) {}
  59. k& operator=(k const&& o) { n_ = o.n_; return *this; }
  60. // No operator==.
  61. private:
  62. int n_;
  63. };
  64. int main() {
  65. { // Copyable and operator== (so checks postconditions).
  66. int x = 123, y = 456;
  67. swap(x, y);
  68. assert(x == 456);
  69. assert(y == 123);
  70. }
  71. { // Non-copyable (so does not check postconditions).
  72. i x{123}, y{456};
  73. swap(x, y);
  74. assert(x == i{456});
  75. assert(y == i{123});
  76. }
  77. { // No operator== (so does not check postconditions).
  78. j x{123}, y{456};
  79. swap(x, y);
  80. // Cannot assert x and y because no operator==.
  81. }
  82. { // Non-copyable and no operator== (so does not check postconditions).
  83. k x{123}, y{456};
  84. swap(x, y);
  85. // Cannot assert x and y because no operator==.
  86. }
  87. return 0;
  88. }