]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson: introduce assert_moveable().
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 28 Jun 2021 23:52:47 +0000 (23:52 +0000)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 29 Jun 2021 14:55:51 +0000 (14:55 +0000)
In C++ `std::moving` a `const`-qualified value yields a constant
r-value reference (`const T&&`) which won't be matched with a callable
taking non-constant r-value reference (like move constructors) but
can play with one taking a constant l-value reference (like copy
constructors do). This behaviour is surprising especially in lambas
where adding or removing the `mutable` specifier may lead to different
behaviour. The problem isn't obvious and it's easy to wrongly drop
the `mutable` druing a clean-up. Therefore introducing a tool for
developers to fail at compile-time if that happens seems desired.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/common/utility.h [new file with mode: 0644]
src/crimson/os/seastore/onode_manager/staged-fltree/node.cc

diff --git a/src/crimson/common/utility.h b/src/crimson/common/utility.h
new file mode 100644 (file)
index 0000000..42c199a
--- /dev/null
@@ -0,0 +1,16 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
+// vim: ts=8 sw=2 smarttab expandtab
+
+#pragma once
+
+#include <type_traits>
+
+template <class T>
+void assert_moveable(T& t) {
+    // It's fine
+}
+template <class T>
+void assert_moveable(const T& t) {
+    static_assert(always_false<T>::value, "unable to move-out from T");
+}
+
index cf585ff53346232864067b747e8c002b894700ee..db68ffb4f515ba484a8c45090c1beec2bd88bad5 100644 (file)
@@ -8,6 +8,7 @@
 #include <sstream>
 
 #include "common/likely.h"
+#include "crimson/common/utility.h"
 #include "crimson/os/seastore/logging.h"
 
 #include "node_extent_manager.h"
@@ -1828,6 +1829,7 @@ LeafNode::erase(context_t c, const search_position_t& pos, bool get_next)
     }
     return seastar::now().then(
         [c, &pos, this_ref = std::move(this_ref), this, FNAME] () mutable {
+      assert_moveable(this_ref);
 #ifndef NDEBUG
       assert(!impl->is_keys_empty());
       if (impl->has_single_value()) {