optional_result_virtual.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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 <boost/optional.hpp>
  7. #include <vector>
  8. #include <cassert>
  9. template<typename T>
  10. class accessible {
  11. public:
  12. virtual T& at(unsigned index, boost::contract::virtual_* v = 0) = 0;
  13. // Could program class invariants and contracts for following too.
  14. virtual T const& operator[](unsigned index) const = 0;
  15. virtual unsigned size() const = 0;
  16. };
  17. //[optional_result_virtual
  18. template<typename T>
  19. T& accessible<T>::at(unsigned index, boost::contract::virtual_* v) {
  20. boost::optional<T&> result;
  21. // Pass `result` right after `v`...
  22. boost::contract::check c = boost::contract::public_function(v, result, this)
  23. .precondition([&] {
  24. BOOST_CONTRACT_ASSERT(index < size());
  25. })
  26. // ...plus postconditions take `result` as a parameter (not capture).
  27. .postcondition([&] (boost::optional<T const&> const& result) {
  28. BOOST_CONTRACT_ASSERT(*result == operator[](index));
  29. })
  30. ;
  31. assert(false);
  32. return *result;
  33. }
  34. //]
  35. template<typename T>
  36. class vector
  37. #define BASES public accessible<T>
  38. : BASES
  39. {
  40. public:
  41. typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types;
  42. #undef BASES
  43. T& at(unsigned index, boost::contract::virtual_* v = 0) /* override */ {
  44. boost::optional<T&> result;
  45. // Pass `result` right after `v`...
  46. boost::contract::check c = boost::contract::public_function<
  47. override_at>(v, result, &vector::at, this, index)
  48. // ...plus postconditions take `result` as parameter (not capture).
  49. .postcondition([&] (boost::optional<T const&> const& result) {
  50. if(index == 0) BOOST_CONTRACT_ASSERT(*result == front());
  51. })
  52. ;
  53. return *(result = vect_[index]);
  54. }
  55. // Could program class invariants and contracts for following too.
  56. T const& operator[](unsigned index) const { return vect_[index]; }
  57. unsigned size() const { return vect_.size(); }
  58. T const& front() const { return vect_.front(); }
  59. void push_back(T const& value) { vect_.push_back(value); }
  60. BOOST_CONTRACT_OVERRIDE(at)
  61. private:
  62. std::vector<T> vect_;
  63. };
  64. int main() {
  65. vector<int> v;
  66. v.push_back(123);
  67. v.push_back(456);
  68. v.push_back(789);
  69. int& x = v.at(1);
  70. assert(x == 456);
  71. x = -456;
  72. assert(v.at(1) == -456);
  73. return 0;
  74. }