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 
5 #ifndef TEST_SUPPORT_TRACKED_HPP
6 #define TEST_SUPPORT_TRACKED_HPP
7 
8 // Define this if you want Tracked objects to print information to stderr.
9 // #define TRACKED_PRINT_STUFF
10 
11 #include <boost/hana/assert.hpp>
12 
13 #ifdef TRACKED_PRINT_STUFF
14 #   include <iostream>
15 #endif
16 
17 #include <iosfwd>
18 
19 
20 struct Tracked {
21     enum class State { CONSTRUCTED, MOVED_FROM, DESTROYED };
22 
23     int value;
24     State state;
25 
TrackedTracked26     explicit Tracked(int k) : value{k}, state{State::CONSTRUCTED} {
27 #ifdef TRACKED_PRINT_STUFF
28         std::cerr << "constructing " << *this << '\n';
29 #endif
30     }
31 
TrackedTracked32     Tracked(Tracked const& t) : value{t.value}, state{State::CONSTRUCTED} {
33         BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
34             "copying a moved-from object");
35 
36         BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
37             "copying a destroyed object");
38 
39 #ifdef TRACKED_PRINT_STUFF
40         std::cerr << "copying " << *this << '\n';
41 #endif
42     }
43 
TrackedTracked44     Tracked(Tracked&& t) : value{t.value}, state{State::CONSTRUCTED} {
45         BOOST_HANA_RUNTIME_CHECK(t.state != State::MOVED_FROM &&
46             "double moving from an object");
47 
48         BOOST_HANA_RUNTIME_CHECK(t.state != State::DESTROYED &&
49             "moving from a destroyed object");
50 
51 #ifdef TRACKED_PRINT_STUFF
52         std::cerr << "moving " << t << '\n';
53 #endif
54         t.state = State::MOVED_FROM;
55     }
56 
operator =Tracked57     Tracked& operator=(Tracked const& other) {
58         BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
59             "assigning to a destroyed object");
60 
61         BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
62             "assigning a moved-from object");
63 
64         BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
65             "assigning a destroyed object");
66 
67 #ifdef TRACKED_PRINT_STUFF
68         std::cerr << "assigning " << other << " to " << *this << '\n';
69 #endif
70         this->value = other.value;
71         return *this;
72     }
73 
operator =Tracked74     Tracked& operator=(Tracked&& other) {
75         BOOST_HANA_RUNTIME_CHECK(this->state != State::DESTROYED &&
76             "assigning to a destroyed object");
77 
78         BOOST_HANA_RUNTIME_CHECK(other.state != State::MOVED_FROM &&
79             "double-moving from an object");
80 
81         BOOST_HANA_RUNTIME_CHECK(other.state != State::DESTROYED &&
82             "assigning a destroyed object");
83 
84 #ifdef TRACKED_PRINT_STUFF
85         std::cerr << "assigning " << other << " to " << *this << '\n';
86 #endif
87         this->value = other.value;
88         other.state = State::MOVED_FROM;
89         return *this;
90     }
91 
~TrackedTracked92     ~Tracked() {
93         BOOST_HANA_RUNTIME_CHECK(state != State::DESTROYED &&
94             "double-destroying an object");
95 
96 #ifdef TRACKED_PRINT_STUFF
97         std::cerr << "destructing " << *this << '\n';
98 #endif
99         state = State::DESTROYED;
100     }
101 
102     template <typename CharT, typename Traits>
103     friend std::basic_ostream<CharT, Traits>&
operator <<(std::basic_ostream<CharT,Traits> & os,Tracked const & t)104     operator<<(std::basic_ostream<CharT, Traits>& os, Tracked const& t) {
105         os << "Tracked{" << t.value << "}";
106         switch (t.state) {
107         case State::CONSTRUCTED:
108             os << "[ok]"; break;
109         case State::MOVED_FROM:
110             os << "[moved from]"; break;
111         case State::DESTROYED:
112             os << "[destroyed]"; break;
113         default:
114             BOOST_HANA_RUNTIME_CHECK(false && "never reached");
115         }
116         return os;
117     }
118 };
119 
120 #endif // !TEST_SUPPORT_TRACKED_HPP
121