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