From 3f82b307aa92f4c8c364f423fd10ec6d3b259ea1 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Tue, 21 Oct 2025 13:01:23 +0100 Subject: [PATCH] fix: rule of 3 for xtimit (#10818) This PR adds a missing move assignment operator, and deletes the copy assignment operator. C++ types should not implement move constructors without also implementing move assignment. This also ensures that `m_fn` is correctly emptied after a move, which is not guaranteed by the standard. This change is also needed to allow `lean::optional` to be eventually replaced by `std::optional`. --- src/util/timeit.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/util/timeit.h b/src/util/timeit.h index 0ffa8fd8c6..ef3237d1c7 100644 --- a/src/util/timeit.h +++ b/src/util/timeit.h @@ -55,10 +55,25 @@ public: } xtimeit(std::function const & fn) : xtimeit(second_duration(0), fn) {} // NOLINT xtimeit(xtimeit const &) = delete; - xtimeit(xtimeit &&) = default; + xtimeit& operator=(xtimeit const &) = delete; + xtimeit(xtimeit && other) noexcept + : m_threshold(std::move(other.m_threshold)), + m_excluded(std::move(other.m_excluded)), + m_start(std::move(other.m_start)), + m_fn(std::move(other.m_fn)) { // TODO: use `std::exchange(_, nullptr)` in C++14 + other.m_fn = nullptr; + } + xtimeit& operator=(xtimeit && other) noexcept { + m_threshold = std::move(other.m_threshold); + m_excluded = std::move(other.m_excluded); + m_start = std::move(other.m_start); + m_fn = std::move(other.m_fn); // TODO: use `std::exchange(_, nullptr)` in C++14 + other.m_fn = nullptr; + } ~xtimeit() { + if (!m_fn) return; auto diff = get_elapsed(); - if (diff >= m_threshold && m_fn) { + if (diff >= m_threshold) { m_fn(diff); } }