]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright Louis Dionne 2013-2016 |
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 | ||
26 | explicit Tracked(int k) : value{k}, state{State::CONSTRUCTED} { | |
27 | #ifdef TRACKED_PRINT_STUFF | |
28 | std::cerr << "constructing " << *this << '\n'; | |
29 | #endif | |
30 | } | |
31 | ||
32 | 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 | ||
44 | 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 | ||
57 | 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 | ||
74 | 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 | ||
92 | ~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>& | |
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 |