friend_invariant.cpp 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  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. #include <boost/contract.hpp>
  6. #include <cassert>
  7. //[friend_invariant
  8. template<typename T>
  9. class positive {
  10. public:
  11. void invariant() const {
  12. BOOST_CONTRACT_ASSERT(value() > 0);
  13. }
  14. // Can be considered an extension of enclosing class' public interface...
  15. friend void swap(positive& object, T& value) {
  16. boost::contract::old_ptr<T> old_object_value =
  17. BOOST_CONTRACT_OLDOF(object.value());
  18. boost::contract::old_ptr<T> old_value = BOOST_CONTRACT_OLDOF(value);
  19. // ...so it can be made to check invariants via `public_function`.
  20. boost::contract::check c = boost::contract::public_function(&object)
  21. .precondition([&] {
  22. BOOST_CONTRACT_ASSERT(value > 0);
  23. })
  24. .postcondition([&] {
  25. BOOST_CONTRACT_ASSERT(object.value() == *old_value);
  26. BOOST_CONTRACT_ASSERT(value == *old_object_value);
  27. })
  28. ;
  29. T saved = object.value_;
  30. object.value_ = value;
  31. value = saved;
  32. }
  33. private:
  34. T value_;
  35. /* ... */
  36. //]
  37. public:
  38. // Could program contracts for following too.
  39. explicit positive(T const& value) : value_(value) {}
  40. T value() const { return value_; }
  41. };
  42. int main() {
  43. positive<int> i(123);
  44. int x = 456;
  45. swap(i, x);
  46. assert(i.value() == 456);
  47. assert(x == 123);
  48. return 0;
  49. }