Make fixed-size Matrix and Array trivially copyable after C++20

Making them trivially copyable allows using std::memcpy() without undefined
behaviors.

Only Matrix and Array with trivially copyable DenseStorage are marked as
trivially copyable with an additional type trait.

As described in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0848r3.html
it requires extremely verbose SFINAE to make the special member functions of
fixed-size Matrix and Array trivial, unless C++20 concepts are available to
simplify the selection of trivial special member functions given template
parameters. Therefore only make this feature available to compilers that support
C++20 P0848R3.

Fix #1855.
This commit is contained in:
Lingzhu Xiang
2022-01-07 19:04:35 +00:00
committed by David Tellenbach
parent c4b1dd2f6b
commit 47eac21072
11 changed files with 127 additions and 2 deletions

View File

@@ -52,6 +52,14 @@ public:
Alignment = actual_alignment
};
};
template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_>
struct has_trivially_copyable_storage<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> >
{
// Must be identical to the type of PlainObjectBase::m_storage.
typedef DenseStorage<Scalar_, internal::size_at_compile_time<MaxRows_, MaxCols_>::ret, Rows_, Cols_, Options_> Storage;
static const bool value = std::is_trivially_copyable<Storage>::value;
};
}
/** \class Matrix
@@ -210,6 +218,12 @@ class Matrix
return Base::_set(other);
}
#if EIGEN_COMP_HAS_P0848R3
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix& operator=(
const Matrix& other) requires internal::has_trivially_copyable_storage<Matrix>::value = default;
#endif
/** \internal
* \brief Copies the value of the expression \a other into \c *this with automatic resizing.
*
@@ -279,6 +293,13 @@ class Matrix
return *this;
}
#if EIGEN_COMP_HAS_P0848R3
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix(Matrix&& other) EIGEN_NOEXCEPT
requires internal::has_trivially_copyable_storage<Matrix>::value = default;
EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE Matrix& operator=(Matrix&& other) EIGEN_NOEXCEPT
requires internal::has_trivially_copyable_storage<Matrix>::value = default;
#endif
/** \copydoc PlainObjectBase(const Scalar&, const Scalar&, const Scalar&, const Scalar&, const ArgTypes&... args)
*
* Example: \include Matrix_variadic_ctor_cxx11.cpp
@@ -404,6 +425,12 @@ class Matrix
EIGEN_STRONG_INLINE Matrix(const Matrix& other) : Base(other)
{ }
#if EIGEN_COMP_HAS_P0848R3
EIGEN_DEVICE_FUNC
EIGEN_STRONG_INLINE Matrix(const Matrix& other) requires internal::has_trivially_copyable_storage<Matrix>::value =
default;
#endif
/** \brief Copy constructor for generic expressions.
* \sa MatrixBase::operator=(const EigenBase<OtherDerived>&)
*/