Skip to content

Commit da11934

Browse files
committed
Fix move constructor / assignment operator
1 parent d922e83 commit da11934

2 files changed

Lines changed: 55 additions & 13 deletions

File tree

include/openPMD/auxiliary/Future.hpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,27 @@ template <typename T>
1111
struct OneTimeTask
1212
{
1313
using task_type = std::function<T()>;
14-
task_type m_task;
15-
bool m_task_valid = true;
14+
// Helper struct so we get auto-generated move constructor / assignment
15+
// operator, but can still override constructors outside
16+
struct Members
17+
{
18+
task_type m_task;
19+
bool m_task_valid = true;
20+
};
21+
Members members;
22+
23+
static constexpr bool noexcept_move =
24+
std::is_move_constructible_v<Members> &&
25+
std::is_move_assignable_v<Members>;
26+
27+
explicit OneTimeTask();
28+
OneTimeTask(task_type);
29+
30+
OneTimeTask(OneTimeTask &&) noexcept(noexcept_move);
31+
OneTimeTask(OneTimeTask const &) = delete;
32+
33+
auto operator=(OneTimeTask &&) noexcept(noexcept_move) -> OneTimeTask &;
34+
auto operator=(OneTimeTask const &) -> OneTimeTask & = delete;
1635

1736
auto operator()() -> T;
1837
};

src/auxiliary/Future.cpp

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,53 @@
1111

1212
namespace openPMD::auxiliary::detail
1313
{
14+
template <typename T>
15+
OneTimeTask<T>::OneTimeTask() = default;
16+
17+
template <typename T>
18+
OneTimeTask<T>::OneTimeTask(task_type task) : members{std::move(task)}
19+
{}
20+
21+
template <typename T>
22+
OneTimeTask<T>::OneTimeTask(OneTimeTask &&other) noexcept(noexcept_move)
23+
: members(std::move(other.members))
24+
{
25+
other.members.m_task_valid = false;
26+
}
27+
28+
template <typename T>
29+
auto OneTimeTask<T>::operator=(OneTimeTask &&other) noexcept(noexcept_move)
30+
-> OneTimeTask &
31+
{
32+
this->members = std::move(other.members);
33+
other.members.m_task_valid = false;
34+
return *this;
35+
}
36+
1437
template <typename T>
1538
auto OneTimeTask<T>::operator()() -> T
1639
{
17-
if (!this->m_task_valid)
40+
if (!members.m_task_valid)
1841
{
1942
throw std::runtime_error(
2043
"[DeferredComputation] No valid state. Probably already "
2144
"computed.");
2245
}
23-
if (!this->m_task)
46+
if (!members.m_task)
2447
{
2548
throw std::runtime_error(
2649
"[DeferredComputation] No valid task was specified.");
2750
}
28-
this->m_task_valid = false;
51+
members.m_task_valid = false;
2952
if constexpr (std::is_void_v<T>)
3053
{
31-
std::move(this->m_task)();
32-
this->m_task = {};
54+
std::move(members.m_task)();
55+
members.m_task = {};
3356
}
3457
else
3558
{
36-
auto res = std::move(this->m_task)();
37-
this->m_task = {}; // reset
59+
auto res = std::move(members.m_task)();
60+
members.m_task = {}; // reset
3861
return res;
3962
}
4063
}
@@ -72,7 +95,7 @@ DeferredComputation<T>::~DeferredComputation()
7295
std::visit(
7396
auxiliary::overloaded{
7497
[](detail::OneTimeTask<T> &task) {
75-
if (task.m_task_valid)
98+
if (task.members.m_task_valid)
7699
{
77100
std::move(task)();
78101
}
@@ -124,8 +147,8 @@ void DeferredComputation<T>::invalidate() &&
124147
std::visit(
125148
auxiliary::overloaded{
126149
[](detail::OneTimeTask<T> &task) {
127-
task.m_task = {};
128-
task.m_task_valid = false;
150+
task.members.m_task = {};
151+
task.members.m_task_valid = false;
129152
},
130153
[](detail::CachedValue<T> const &) {}},
131154
this->m_task);
@@ -137,7 +160,7 @@ auto DeferredComputation<T>::valid() const noexcept -> bool
137160
return std::visit(
138161
auxiliary::overloaded{
139162
[](detail::OneTimeTask<T> const &task) {
140-
return task.m_task_valid;
163+
return task.members.m_task_valid;
141164
},
142165
[](detail::CachedValue<T> const &) { return true; }},
143166
this->m_task);

0 commit comments

Comments
 (0)