--- /dev/null
+#ifndef SUPPORT_TRACKED_VALUE_H
+#define SUPPORT_TRACKED_VALUE_H
+
+#include <cassert>
+
+struct TrackedValue {
+ enum State { CONSTRUCTED, MOVED_FROM, DESTROYED };
+ State state;
+
+ TrackedValue() : state(State::CONSTRUCTED) {}
+
+ TrackedValue(TrackedValue const& t) : state(State::CONSTRUCTED) {
+ assert(t.state != State::MOVED_FROM && "copying a moved-from object");
+ assert(t.state != State::DESTROYED && "copying a destroyed object");
+ }
+
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+ TrackedValue(TrackedValue&& t) : state(State::CONSTRUCTED) {
+ assert(t.state != State::MOVED_FROM && "double moving from an object");
+ assert(t.state != State::DESTROYED && "moving from a destroyed object");
+ t.state = State::MOVED_FROM;
+ }
+#endif
+
+ TrackedValue& operator=(TrackedValue const& t) {
+ assert(state != State::DESTROYED && "copy assigning into destroyed object");
+ assert(t.state != State::MOVED_FROM && "copying a moved-from object");
+ assert(t.state != State::DESTROYED && "copying a destroyed object");
+ state = t.state;
+ return *this;
+ }
+
+#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
+ TrackedValue& operator=(TrackedValue&& t) {
+ assert(state != State::DESTROYED && "move assigning into destroyed object");
+ assert(t.state != State::MOVED_FROM && "double moving from an object");
+ assert(t.state != State::DESTROYED && "moving from a destroyed object");
+ state = t.state;
+ t.state = State::MOVED_FROM;
+ return *this;
+ }
+#endif
+
+ ~TrackedValue() {
+ assert(state != State::DESTROYED && "double-destroying an object");
+ state = State::DESTROYED;
+ }
+};
+
+#endif // SUPPORT_TRACKED_VALUE_H