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:
		
							parent
							
								
									c4b1dd2f6b
								
							
						
					
					
						commit
						47eac21072
					
				| @ -21,6 +21,10 @@ struct traits<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> > : tra | ||||
|   typedef ArrayXpr XprKind; | ||||
|   typedef ArrayBase<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> > XprBase; | ||||
| }; | ||||
| 
 | ||||
| template<typename Scalar_, int Rows_, int Cols_, int Options_, int MaxRows_, int MaxCols_> | ||||
| struct has_trivially_copyable_storage<Array<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> > | ||||
|     : has_trivially_copyable_storage<Matrix<Scalar_, Rows_, Cols_, Options_, MaxRows_, MaxCols_> > {}; | ||||
| } | ||||
| 
 | ||||
| /** \class Array
 | ||||
| @ -120,6 +124,12 @@ class Array | ||||
|       return Base::_set(other); | ||||
|     } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE Array& operator=( | ||||
|         const Array& other) requires internal::has_trivially_copyable_storage<Array>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     /** Default constructor.
 | ||||
|       * | ||||
|       * For fixed-size matrices, does nothing. | ||||
| @ -159,6 +169,13 @@ class Array | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC Array(Array&& other) EIGEN_NOEXCEPT | ||||
|         requires internal::has_trivially_copyable_storage<Array>::value = default; | ||||
|     EIGEN_DEVICE_FUNC Array& operator=(Array&& other) EIGEN_NOEXCEPT | ||||
|         requires internal::has_trivially_copyable_storage<Array>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     /** \copydoc PlainObjectBase(const Scalar& a0, const Scalar& a1, const Scalar& a2, const Scalar& a3, const ArgTypes&... args)
 | ||||
|      * | ||||
|      * Example: \include Array_variadic_ctor_cxx11.cpp | ||||
| @ -266,6 +283,12 @@ class Array | ||||
|             : Base(other) | ||||
|     { } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE Array(const Array& other) requires internal::has_trivially_copyable_storage<Array>::value = | ||||
|         default; | ||||
| #endif | ||||
| 
 | ||||
|   private: | ||||
|     struct PrivateType {}; | ||||
|   public: | ||||
|  | ||||
| @ -112,6 +112,11 @@ template<typename Derived> class ArrayBase | ||||
|       return derived(); | ||||
|     } | ||||
|      | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE ArrayBase& operator=( | ||||
|         const ArrayBase& other) requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     /** Set all the entries to \a value.
 | ||||
|       * \sa DenseBase::setConstant(), DenseBase::fill() */ | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE | ||||
|  | ||||
| @ -275,6 +275,11 @@ template<typename Derived> class DenseBase | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE | ||||
|     Derived& operator=(const DenseBase& other); | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE DenseBase& operator=( | ||||
|         const DenseBase& other) requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     template<typename OtherDerived> | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     Derived& operator=(const EigenBase<OtherDerived> &other); | ||||
|  | ||||
| @ -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>&) | ||||
|       */ | ||||
|  | ||||
| @ -140,6 +140,11 @@ template<typename Derived> class MatrixBase | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE | ||||
|     Derived& operator=(const MatrixBase& other); | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE MatrixBase& operator=( | ||||
|         const MatrixBase& other) requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     // We cannot inherit here via Base::operator= since it is causing
 | ||||
|     // trouble with MSVC.
 | ||||
| 
 | ||||
|  | ||||
| @ -463,6 +463,12 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type | ||||
|       return _set(other); | ||||
|     } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE PlainObjectBase& operator=( | ||||
|         const PlainObjectBase& other) requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     /** \sa MatrixBase::lazyAssign() */ | ||||
|     template<typename OtherDerived> | ||||
|     EIGEN_DEVICE_FUNC | ||||
| @ -514,10 +520,27 @@ class PlainObjectBase : public internal::dense_xpr_base<Derived>::type | ||||
|       return *this; | ||||
|     } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     PlainObjectBase(PlainObjectBase&& other) EIGEN_NOEXCEPT | ||||
|         requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| 
 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     PlainObjectBase& operator=(PlainObjectBase&& other) EIGEN_NOEXCEPT | ||||
|         requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     /** Copy constructor */ | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE PlainObjectBase(const PlainObjectBase& other) | ||||
|       : Base(), m_storage(other.m_storage) { } | ||||
| 
 | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE PlainObjectBase( | ||||
|         const PlainObjectBase& other) requires internal::has_trivially_copyable_storage<Derived>::value = default; | ||||
| #endif | ||||
| 
 | ||||
|     EIGEN_DEVICE_FUNC | ||||
|     EIGEN_STRONG_INLINE PlainObjectBase(Index size, Index rows, Index cols) | ||||
|       : m_storage(size, rows, cols) | ||||
|  | ||||
| @ -42,6 +42,11 @@ template<typename T> struct evaluator_traits; | ||||
| 
 | ||||
| template< typename T> struct evaluator; | ||||
| 
 | ||||
| template<typename T> struct has_trivially_copyable_storage | ||||
| { | ||||
|   static const bool value = false; | ||||
| }; | ||||
| 
 | ||||
| } // end namespace internal
 | ||||
| 
 | ||||
| template<typename T> struct NumTraits; | ||||
|  | ||||
| @ -1084,6 +1084,16 @@ namespace Eigen { | ||||
|     } | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * \internal | ||||
|  * \brief Macro for conditionally trivial special member functions for supporting trivially copyable types. | ||||
|  * This feature is officially known as C++20's P0848R3 and is enabled on supported compilers. | ||||
|  */ | ||||
| #if (EIGEN_COMP_CXXVER >= 20) && (EIGEN_COMP_GNUC_STRICT || EIGEN_COMP_MSVC_STRICT) | ||||
| #define EIGEN_COMP_HAS_P0848R3 1 | ||||
| #else | ||||
| #define EIGEN_COMP_HAS_P0848R3 0 | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
|  * \internal | ||||
|  | ||||
| @ -20,6 +20,11 @@ static_assert(std::is_trivially_move_assignable<DenseStorageD3x3>::value, "Dense | ||||
| static_assert(std::is_trivially_copy_constructible<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_constructible"); | ||||
| static_assert(std::is_trivially_copy_assignable<DenseStorageD3x3>::value, "DenseStorage not trivially_copy_assignable"); | ||||
| static_assert(std::is_trivially_copyable<DenseStorageD3x3>::value, "DenseStorage not trivially_copyable"); | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
| static_assert(std::is_trivially_copyable<Eigen::Matrix3d>::value, "Eigen::Matrix3d not trivially_copyable"); | ||||
| static_assert(std::is_trivially_copyable<Eigen::Array33d>::value, "Eigen::Array33d not trivially_copyable"); | ||||
| static_assert(!std::is_trivially_copyable<Eigen::Matrix3<AnnoyingScalar>>::value, "Eigen::Matrix3<AnnoyingScalar> is trivially_copyable"); | ||||
| #endif | ||||
| #endif | ||||
| 
 | ||||
| template <typename T, int Size, int Rows, int Cols> | ||||
|  | ||||
| @ -39,6 +39,16 @@ | ||||
| #include <iterator> | ||||
| #include <numeric> | ||||
| #include <random> | ||||
| 
 | ||||
| // C++20 libstdc++'s headers have non-parenthesized calls to max() and min(). | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
| #ifdef max | ||||
| #undef max | ||||
| #endif | ||||
| #ifdef min | ||||
| #undef min | ||||
| #endif | ||||
| #endif | ||||
| #include <thread> | ||||
| 
 | ||||
| #if defined(EIGEN_USE_THREADS) || defined(EIGEN_USE_SYCL) | ||||
|  | ||||
| @ -39,9 +39,7 @@ | ||||
| #include <condition_variable> | ||||
| #include <deque> | ||||
| #include <mutex> | ||||
| #include <thread> | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <utility> | ||||
| 
 | ||||
| // There are non-parenthesized calls to "max" in the  <unordered_map> header, | ||||
| @ -53,6 +51,15 @@ | ||||
| #endif | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| // C++20 libstdc++'s headers also calls "max" and "min" indirectly. | ||||
| #if EIGEN_COMP_HAS_P0848R3 | ||||
| #ifdef min | ||||
| #undef min | ||||
| #endif | ||||
| #endif | ||||
| #include <thread> | ||||
| #include <memory> | ||||
| 
 | ||||
| #include "src/util/CXX11Meta.h" | ||||
| #include "src/util/MaxSizeVector.h" | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Lingzhu Xiang
						Lingzhu Xiang