46 std::atomic_size_t _dtor{0};
47 std::atomic_size_t _copy_ctor{0};
48 std::atomic_size_t _move_ctor{0};
49 std::atomic_size_t _copy_assign_lhs{0};
50 std::atomic_size_t _copy_assign_rhs{0};
51 std::atomic_size_t _move_assign_lhs{0};
52 std::atomic_size_t _move_assign_rhs{0};
53 std::atomic_size_t _swap{0};
54 std::atomic_size_t _equality{0};
56 std::condition_variable _condition;
58 auto remaining()
const -> std::size_t {
return _copy_ctor + _move_ctor - _dtor + 1; }
60 void wait(std::size_t count) {
62 std::unique_lock<std::mutex> lock(_mutex);
63 _condition.wait(lock, [&] {
return count == remaining(); });
67 friend inline auto operator<<(std::ostream& out,
const annotate_counters& x) -> std::ostream& {
68 out <<
" dtor: " << x._dtor <<
"\n";
69 out <<
" copy_ctor: " << x._copy_ctor <<
"\n";
70 out <<
" move_ctor: " << x._move_ctor <<
"\n";
71 out <<
"copy_assign_lhs: " << x._copy_assign_lhs <<
"\n";
72 out <<
"copy_assign_rhs: " << x._copy_assign_rhs <<
"\n";
73 out <<
"move_assign_lhs: " << x._move_assign_lhs <<
"\n";
74 out <<
"move_assign_rhs: " << x._move_assign_rhs <<
"\n";
75 out <<
" swap: " << x._swap <<
"\n";
76 out <<
" equality: " << x._equality <<
"\n";
94 _counters->_condition.notify_one();
98 annotate(
const annotate& x) : _counters(x._counters) { ++_counters->_copy_ctor; }
99 annotate(annotate&& x) noexcept : _counters(x._counters) { ++_counters->_move_ctor; }
101 auto operator=(
const annotate& x) -> annotate& {
102 if (
this == &x)
return *
this;
103 ++x._counters->_copy_assign_rhs;
104 ++_counters->_copy_assign_lhs;
107 auto operator=(annotate&& x)
noexcept -> annotate& {
108 ++x._counters->_move_assign_rhs;
109 ++_counters->_move_assign_lhs;
113 friend inline void swap(annotate& x, annotate& y)
noexcept {
114 ++x._counters->_swap;
115 ++y._counters->_swap;
118 friend inline auto operator==(
const annotate& x,
const annotate& y) ->
bool {
119 ++x._counters->_equality;
120 ++y._counters->_equality;
123 friend inline auto operator!=(
const annotate& x,
const annotate& y) ->
bool {
137 explicit regular(
int x) : _x(x) { std::cout << _x <<
" ctor" <<
'\n'; }
138 ~regular() { std::cout << _x <<
" dtor" <<
'\n'; }
140 regular(
const regular& rhs) : _x(rhs._x) { std::cout << _x <<
" copy-ctor" <<
'\n'; }
141 regular(regular&& rhs) noexcept : _x(rhs._x) {
142 std::cout << _x <<
" move-ctor" <<
'\n';
146 auto operator=(
const regular& rhs) -> regular& {
147 std::cout << _x <<
" assign" <<
'\n';
148 if (&rhs ==
this)
return *
this;
152 auto operator=(regular&& rhs)
noexcept -> regular& {
153 std::cout << _x <<
" move-assign" <<
'\n';
159 friend inline void swap(regular& lhs, regular& rhs)
noexcept {
160 std::cout << lhs._x <<
"/" << rhs._x <<
" swap " <<
'\n';
161 std::swap(lhs._x, rhs._x);
164 friend inline auto operator==(
const regular& lhs,
const regular& rhs) ->
bool {
165 return lhs._x == rhs._x;
167 friend inline auto operator!=(
const regular& lhs,
const regular& rhs) ->
bool {
168 return !(lhs == rhs);
171 friend inline auto operator<(
const regular& lhs,
const regular& rhs) ->
bool {
172 bool result(lhs._x < rhs._x);
173 std::cout << lhs._x <<
" < " << rhs._x <<
": " << std::boolalpha << result <<
'\n';