blob: b0869b23bdcbb92f9eb67cd76f21342c151bd2c3 [file] [log] [blame]
Eric Fiselier3c7b8012015-03-09 18:02:16 +00001#ifndef SUPPORT_TRACKED_VALUE_H
2#define SUPPORT_TRACKED_VALUE_H
3
4#include <cassert>
5
6struct TrackedValue {
7 enum State { CONSTRUCTED, MOVED_FROM, DESTROYED };
8 State state;
9
10 TrackedValue() : state(State::CONSTRUCTED) {}
11
12 TrackedValue(TrackedValue const& t) : state(State::CONSTRUCTED) {
13 assert(t.state != State::MOVED_FROM && "copying a moved-from object");
14 assert(t.state != State::DESTROYED && "copying a destroyed object");
15 }
16
17#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
18 TrackedValue(TrackedValue&& t) : state(State::CONSTRUCTED) {
19 assert(t.state != State::MOVED_FROM && "double moving from an object");
20 assert(t.state != State::DESTROYED && "moving from a destroyed object");
21 t.state = State::MOVED_FROM;
22 }
23#endif
24
25 TrackedValue& operator=(TrackedValue const& t) {
26 assert(state != State::DESTROYED && "copy assigning into destroyed object");
27 assert(t.state != State::MOVED_FROM && "copying a moved-from object");
28 assert(t.state != State::DESTROYED && "copying a destroyed object");
29 state = t.state;
30 return *this;
31 }
32
33#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
34 TrackedValue& operator=(TrackedValue&& t) {
35 assert(state != State::DESTROYED && "move assigning into destroyed object");
36 assert(t.state != State::MOVED_FROM && "double moving from an object");
37 assert(t.state != State::DESTROYED && "moving from a destroyed object");
38 state = t.state;
39 t.state = State::MOVED_FROM;
40 return *this;
41 }
42#endif
43
44 ~TrackedValue() {
45 assert(state != State::DESTROYED && "double-destroying an object");
46 state = State::DESTROYED;
47 }
48};
49
50#endif // SUPPORT_TRACKED_VALUE_H