Drake
is_memcpy_movable.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdlib>
4 #include <cstring>
5 #include <functional>
6 #include <memory>
7 #include <type_traits>
8 
9 namespace drake {
10 namespace test {
11 /// Checks if @p value of @p T type is movable via memcpy. That is, it tests
12 /// memcpy on @p value keeps a given invariant between @p value and a copy of
13 /// it. It uses a binary function object @p invariant_pred to check for
14 /// invariance.
15 ///
16 /// @note Eigen's reallocation mechanisms have an issue. It is moving bytes
17 /// using `memcpy` without calling a move constructor. As a result, if a
18 /// `Scalar` type of Eigen matrix/array is not IsMemcpyMovable, we have
19 /// undefined behavior when `conservativeResize` method is called. This should
20 /// *always* be used to test a `Scalar` used within an `Eigen::EigenBase<...>`
21 /// object. Please see https://github.com/RobotLocomotion/drake/issues/5974 for
22 /// more information.
23 template <typename T, typename InvariantPred = std::equal_to<T>>
24 bool IsMemcpyMovable(const T& value,
25  const InvariantPred& invariant_pred = InvariantPred()) {
26  // 1. Create ptr_to_original via placement-new.
27  auto original_storage = std::make_unique<
28  typename std::aligned_storage<sizeof(T), alignof(T)>::type>();
29  T* const ptr_to_original{new (original_storage.get()) T{value}};
30 
31  // 2. Create ptr_to_moved from ptr_to_original via memcpy.
32  auto moved_storage = std::make_unique<
33  typename std::aligned_storage<sizeof(T), alignof(T)>::type>();
34  T* const ptr_to_moved{reinterpret_cast<T* const>(moved_storage.get())};
35  memcpy(ptr_to_moved, ptr_to_original, sizeof(T));
36 
37  // 3. Free original_storage.
38  original_storage.reset();
39 
40  // 4. Check if the invariant between value and ptr_to_moved hold.
41  const bool out{invariant_pred(value, *ptr_to_moved)};
42 
43  ptr_to_moved->T::~T();
44  return out;
45 }
46 } // namespace test
47 } // namespace drake
Definition: automotive_demo.cc:88
bool IsMemcpyMovable(const T &value, const InvariantPred &invariant_pred=InvariantPred())
Checks if value of T type is movable via memcpy.
Definition: is_memcpy_movable.h:24
int value
Definition: copyable_unique_ptr_test.cc:61