tracked.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #ifndef TEST_SUPPORT_TRACKED_HPP
  5. #define TEST_SUPPORT_TRACKED_HPP
  6. // Define this if you want Tracked objects to print information to stderr.
  7. // #define TRACKED_PRINT_STUFF
  8. #include <boost/hana/assert.hpp>
  9. #ifdef TRACKED_PRINT_STUFF
  10. # include <iostream>
  11. #endif
  12. #include <iosfwd>
  13. struct Tracked {
  14. enum class State { CONSTRUCTED, MOVED_FROM, DESTROYED };
  15. int value;
  16. State state;
  17. explicit Tracked(int k) : value{k}, state{State::CONSTRUCTED} {
  18. #ifdef TRACKED_PRINT_STUFF
  19. std::cerr << "constructing " << *this << '\n';
  20. #endif
  21. }
  22. Tracked(Tracked const& t) : value{t.value}, state{State::CONSTRUCTED} {
  23. BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
  24. "copying a moved-from object");
  25. BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
  26. "copying a destroyed object");
  27. #ifdef TRACKED_PRINT_STUFF
  28. std::cerr << "copying " << *this << '\n';
  29. #endif
  30. }
  31. Tracked(Tracked&& t) : value{t.value}, state{State::CONSTRUCTED} {
  32. BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
  33. "double moving from an object");
  34. BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
  35. "moving from a destroyed object");
  36. #ifdef TRACKED_PRINT_STUFF
  37. std::cerr << "moving " << t << '\n';
  38. #endif
  39. t.state = State::MOVED_FROM;
  40. }
  41. Tracked& operator=(Tracked const& other) {
  42. BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
  43. "assigning to a destroyed object");
  44. BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
  45. "assigning a moved-from object");
  46. BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
  47. "assigning a destroyed object");
  48. #ifdef TRACKED_PRINT_STUFF
  49. std::cerr << "assigning " << other << " to " << *this << '\n';
  50. #endif
  51. this->value = other.value;
  52. return *this;
  53. }
  54. Tracked& operator=(Tracked&& other) {
  55. BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
  56. "assigning to a destroyed object");
  57. BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
  58. "double-moving from an object");
  59. BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
  60. "assigning a destroyed object");
  61. #ifdef TRACKED_PRINT_STUFF
  62. std::cerr << "assigning " << other << " to " << *this << '\n';
  63. #endif
  64. this->value = other.value;
  65. other.state = State::MOVED_FROM;
  66. return *this;
  67. }
  68. ~Tracked() {
  69. BOOST_HANA_RUNTIME_CHECK(state != State::DESTROYED &&
  70. "double-destroying an object");
  71. #ifdef TRACKED_PRINT_STUFF
  72. std::cerr << "destructing " << *this << '\n';
  73. #endif
  74. state = State::DESTROYED;
  75. }
  76. template <typename CharT, typename Traits>
  77. friend std::basic_ostream<CharT, Traits>&
  78. operator<<(std::basic_ostream<CharT, Traits>& os, Tracked const& t) {
  79. os << "Tracked{" << t.value << "}";
  80. switch (t.state) {
  81. case State::CONSTRUCTED:
  82. os << "[ok]"; break;
  83. case State::MOVED_FROM:
  84. os << "[moved from]"; break;
  85. case State::DESTROYED:
  86. os << "[destroyed]"; break;
  87. default:
  88. BOOST_HANA_RUNTIME_CHECK(false && "never reached");
  89. }
  90. return os;
  91. }
  92. };
  93. #endif // !TEST_SUPPORT_TRACKED_HPP