1*0a6a1f1dSLionel Sambuc #ifndef SUPPORT_TRACKED_VALUE_H 2*0a6a1f1dSLionel Sambuc #define SUPPORT_TRACKED_VALUE_H 3*0a6a1f1dSLionel Sambuc 4*0a6a1f1dSLionel Sambuc #include <cassert> 5*0a6a1f1dSLionel Sambuc 6*0a6a1f1dSLionel Sambuc struct TrackedValue { 7*0a6a1f1dSLionel Sambuc enum State { CONSTRUCTED, MOVED_FROM, DESTROYED }; 8*0a6a1f1dSLionel Sambuc State state; 9*0a6a1f1dSLionel Sambuc TrackedValueTrackedValue10*0a6a1f1dSLionel Sambuc TrackedValue() : state(State::CONSTRUCTED) {} 11*0a6a1f1dSLionel Sambuc TrackedValueTrackedValue12*0a6a1f1dSLionel Sambuc TrackedValue(TrackedValue const& t) : state(State::CONSTRUCTED) { 13*0a6a1f1dSLionel Sambuc assert(t.state != State::MOVED_FROM && "copying a moved-from object"); 14*0a6a1f1dSLionel Sambuc assert(t.state != State::DESTROYED && "copying a destroyed object"); 15*0a6a1f1dSLionel Sambuc } 16*0a6a1f1dSLionel Sambuc 17*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES TrackedValueTrackedValue18*0a6a1f1dSLionel Sambuc TrackedValue(TrackedValue&& t) : state(State::CONSTRUCTED) { 19*0a6a1f1dSLionel Sambuc assert(t.state != State::MOVED_FROM && "double moving from an object"); 20*0a6a1f1dSLionel Sambuc assert(t.state != State::DESTROYED && "moving from a destroyed object"); 21*0a6a1f1dSLionel Sambuc t.state = State::MOVED_FROM; 22*0a6a1f1dSLionel Sambuc } 23*0a6a1f1dSLionel Sambuc #endif 24*0a6a1f1dSLionel Sambuc 25*0a6a1f1dSLionel Sambuc TrackedValue& operator=(TrackedValue const& t) { 26*0a6a1f1dSLionel Sambuc assert(state != State::DESTROYED && "copy assigning into destroyed object"); 27*0a6a1f1dSLionel Sambuc assert(t.state != State::MOVED_FROM && "copying a moved-from object"); 28*0a6a1f1dSLionel Sambuc assert(t.state != State::DESTROYED && "copying a destroyed object"); 29*0a6a1f1dSLionel Sambuc state = t.state; 30*0a6a1f1dSLionel Sambuc return *this; 31*0a6a1f1dSLionel Sambuc } 32*0a6a1f1dSLionel Sambuc 33*0a6a1f1dSLionel Sambuc #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES 34*0a6a1f1dSLionel Sambuc TrackedValue& operator=(TrackedValue&& t) { 35*0a6a1f1dSLionel Sambuc assert(state != State::DESTROYED && "move assigning into destroyed object"); 36*0a6a1f1dSLionel Sambuc assert(t.state != State::MOVED_FROM && "double moving from an object"); 37*0a6a1f1dSLionel Sambuc assert(t.state != State::DESTROYED && "moving from a destroyed object"); 38*0a6a1f1dSLionel Sambuc state = t.state; 39*0a6a1f1dSLionel Sambuc t.state = State::MOVED_FROM; 40*0a6a1f1dSLionel Sambuc return *this; 41*0a6a1f1dSLionel Sambuc } 42*0a6a1f1dSLionel Sambuc #endif 43*0a6a1f1dSLionel Sambuc ~TrackedValueTrackedValue44*0a6a1f1dSLionel Sambuc ~TrackedValue() { 45*0a6a1f1dSLionel Sambuc assert(state != State::DESTROYED && "double-destroying an object"); 46*0a6a1f1dSLionel Sambuc state = State::DESTROYED; 47*0a6a1f1dSLionel Sambuc } 48*0a6a1f1dSLionel Sambuc }; 49*0a6a1f1dSLionel Sambuc 50*0a6a1f1dSLionel Sambuc #endif // SUPPORT_TRACKED_VALUE_H 51