Add construct_at, destroy_at wrappers. Use throughout.

This commit is contained in:
Tobias Schlüter 2022-03-08 20:43:22 +00:00 committed by Rasmus Munk Larsen
parent dfa5176780
commit cd2ba9d03e
18 changed files with 78 additions and 51 deletions

View File

@ -1723,14 +1723,14 @@ struct evaluator<EvalToTemp<ArgType> >
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
: m_result(xpr.arg()) : m_result(xpr.arg())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
} }
// This constructor is used when nesting an EvalTo evaluator in another evaluator // This constructor is used when nesting an EvalTo evaluator in another evaluator
EIGEN_DEVICE_FUNC evaluator(const ArgType& arg) EIGEN_DEVICE_FUNC evaluator(const ArgType& arg)
: m_result(arg) : m_result(arg)
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
} }
protected: protected:

View File

@ -104,7 +104,7 @@ struct unary_evaluator<Inverse<ArgType> >
unary_evaluator(const InverseType& inv_xpr) unary_evaluator(const InverseType& inv_xpr)
: m_result(inv_xpr.rows(), inv_xpr.cols()) : m_result(inv_xpr.rows(), inv_xpr.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
internal::call_assignment_no_alias(m_result, inv_xpr); internal::call_assignment_no_alias(m_result, inv_xpr);
} }

View File

@ -109,7 +109,7 @@ struct product_evaluator<Product<Lhs, Rhs, Options>, ProductTag, LhsShape, RhsSh
explicit product_evaluator(const XprType& xpr) explicit product_evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols()) : m_result(xpr.rows(), xpr.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
// FIXME shall we handle nested_eval here?, // FIXME shall we handle nested_eval here?,
// if so, then we must take care at removing the call to nested_eval in the specializations (e.g., in permutation_matrix_product, transposition_matrix_product, etc.) // if so, then we must take care at removing the call to nested_eval in the specializations (e.g., in permutation_matrix_product, transposition_matrix_product, etc.)

View File

@ -199,8 +199,8 @@ protected:
return false; return false;
} }
::new (static_cast<Base*>(this)) Base(expr.data(), rows, cols); internal::construct_at<Base>(this, expr.data(), rows, cols);
::new (&m_stride) StrideBase( internal::construct_at(&m_stride,
(StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride, (StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride,
(StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride ); (StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride );
return true; return true;

View File

@ -106,7 +106,7 @@ struct evaluator<ReturnByValue<Derived> >
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr) EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols()) : m_result(xpr.rows(), xpr.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
xpr.evalTo(m_result); xpr.evalTo(m_result);
} }

View File

@ -125,7 +125,7 @@ struct evaluator<Solve<Decomposition,RhsType> >
EIGEN_DEVICE_FUNC explicit evaluator(const SolveType& solve) EIGEN_DEVICE_FUNC explicit evaluator(const SolveType& solve)
: m_result(solve.rows(), solve.cols()) : m_result(solve.rows(), solve.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
solve.dec()._solve_impl(solve.rhs(), m_result); solve.dec()._solve_impl(solve.rhs(), m_result);
} }

View File

@ -1150,6 +1150,38 @@ inline int queryTopLevelCacheSize()
return (std::max)(l2,l3); return (std::max)(l2,l3);
} }
/** \internal
* This wraps C++20's std::construct_at, using placement new instead if it is not available.
*/
#if EIGEN_COMP_CXXVER >= 20
using std::construct_at;
#else
template<class T, class... Args>
T* construct_at( T* p, Args&&... args )
{
return ::new (const_cast<void*>(static_cast<const volatile void*>(p)))
T(std::forward<Args>(args)...);
}
#endif
/** \internal
* This wraps C++17's std::destroy_at. If it's not available it calls the destructor.
* The wrapper is not a full replacement for C++20's std::destroy_at as it cannot
* be applied to std::array.
*/
#if EIGEN_COMP_CXXVER >= 17
using std::destroy_at;
#else
template<class T>
void destroy_at(T* p)
{
p->~T();
}
#endif
} // end namespace internal } // end namespace internal
} // end namespace Eigen } // end namespace Eigen

View File

@ -345,7 +345,7 @@ struct unary_evaluator<Homogeneous<ArgType,Direction>, IndexBased>
EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op) EIGEN_DEVICE_FUNC explicit unary_evaluator(const XprType& op)
: Base(), m_temp(op) : Base(), m_temp(op)
{ {
::new (static_cast<Base*>(this)) Base(m_temp); internal::construct_at<Base>(this, m_temp);
} }
protected: protected:

View File

@ -79,16 +79,16 @@ public:
template<typename MatrixDerived> template<typename MatrixDerived>
void grab(const EigenBase<MatrixDerived> &mat) void grab(const EigenBase<MatrixDerived> &mat)
{ {
m_matrix.~Ref<const MatrixType>(); internal::destroy_at(&m_matrix);
::new (&m_matrix) Ref<const MatrixType>(mat.derived()); internal::construct_at(&m_matrix, mat.derived());
} }
void grab(const Ref<const MatrixType> &mat) void grab(const Ref<const MatrixType> &mat)
{ {
if(&(mat.derived()) != &m_matrix) if(&(mat.derived()) != &m_matrix)
{ {
m_matrix.~Ref<const MatrixType>(); internal::destroy_at(&m_matrix);
::new (&m_matrix) Ref<const MatrixType>(mat); internal::construct_at(&m_matrix, mat);
} }
} }

View File

@ -85,7 +85,7 @@ struct evaluator<SolveWithGuess<Decomposition,RhsType, GuessType> >
evaluator(const SolveType& solve) evaluator(const SolveType& solve)
: m_result(solve.rows(), solve.cols()) : m_result(solve.rows(), solve.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
m_result = solve.guess(); m_result = solve.guess();
solve.dec()._solve_with_guess_impl(solve.rhs(), m_result); solve.dec()._solve_with_guess_impl(solve.rhs(), m_result);
} }

View File

@ -265,16 +265,16 @@ class KLU : public SparseSolverBase<KLU<MatrixType_> >
template<typename MatrixDerived> template<typename MatrixDerived>
void grab(const EigenBase<MatrixDerived> &A) void grab(const EigenBase<MatrixDerived> &A)
{ {
mp_matrix.~KLUMatrixRef(); internal::destroy_at(&mp_matrix);
::new (&mp_matrix) KLUMatrixRef(A.derived()); internal::construct_at(&mp_matrix, A.derived());
} }
void grab(const KLUMatrixRef &A) void grab(const KLUMatrixRef &A)
{ {
if(&(A.derived()) != &mp_matrix) if(&(A.derived()) != &mp_matrix)
{ {
mp_matrix.~KLUMatrixRef(); internal::destroy_at(&mp_matrix);
::new (&mp_matrix) KLUMatrixRef(A); internal::construct_at(&mp_matrix, A);
} }
} }

View File

@ -73,8 +73,8 @@ class qr_preconditioner_impl<MatrixType, Options, FullPivHouseholderQRPreconditi
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.rows(), svd.cols()); internal::construct_at(&m_qr, svd.rows(), svd.cols());
} }
if (svd.m_computeFullU) m_workspace.resize(svd.rows()); if (svd.m_computeFullU) m_workspace.resize(svd.rows());
} }
@ -119,8 +119,8 @@ class qr_preconditioner_impl<MatrixType, Options, FullPivHouseholderQRPreconditi
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.cols(), svd.rows()); internal::construct_at(&m_qr, svd.cols(), svd.rows());
} }
m_adjoint.resize(svd.cols(), svd.rows()); m_adjoint.resize(svd.cols(), svd.rows());
if (svd.m_computeFullV) m_workspace.resize(svd.cols()); if (svd.m_computeFullV) m_workspace.resize(svd.cols());
@ -165,8 +165,8 @@ class qr_preconditioner_impl<MatrixType, Options, ColPivHouseholderQRPreconditio
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.rows(), svd.cols()); internal::construct_at(&m_qr, svd.rows(), svd.cols());
} }
if (svd.m_computeFullU) m_workspace.resize(svd.rows()); if (svd.m_computeFullU) m_workspace.resize(svd.rows());
else if (svd.m_computeThinU) m_workspace.resize(svd.cols()); else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
@ -221,8 +221,8 @@ class qr_preconditioner_impl<MatrixType, Options, ColPivHouseholderQRPreconditio
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.cols(), svd.rows()); internal::construct_at(&m_qr, svd.cols(), svd.rows());
} }
if (svd.m_computeFullV) m_workspace.resize(svd.cols()); if (svd.m_computeFullV) m_workspace.resize(svd.cols());
else if (svd.m_computeThinV) m_workspace.resize(svd.rows()); else if (svd.m_computeThinV) m_workspace.resize(svd.rows());
@ -273,8 +273,8 @@ class qr_preconditioner_impl<MatrixType, Options, HouseholderQRPreconditioner, P
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols()) if (svd.rows() != m_qr.rows() || svd.cols() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.rows(), svd.cols()); internal::construct_at(&m_qr, svd.rows(), svd.cols());
} }
if (svd.m_computeFullU) m_workspace.resize(svd.rows()); if (svd.m_computeFullU) m_workspace.resize(svd.rows());
else if (svd.m_computeThinU) m_workspace.resize(svd.cols()); else if (svd.m_computeThinU) m_workspace.resize(svd.cols());
@ -328,8 +328,8 @@ class qr_preconditioner_impl<MatrixType, Options, HouseholderQRPreconditioner, P
void allocate(const SVDType& svd) { void allocate(const SVDType& svd) {
if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols()) if (svd.cols() != m_qr.rows() || svd.rows() != m_qr.cols())
{ {
m_qr.~QRType(); internal::destroy_at(&m_qr);
::new (&m_qr) QRType(svd.cols(), svd.rows()); internal::construct_at(&m_qr, svd.cols(), svd.rows());
} }
if (svd.m_computeFullV) m_workspace.resize(svd.cols()); if (svd.m_computeFullV) m_workspace.resize(svd.cols());
else if (svd.m_computeThinV) m_workspace.resize(svd.rows()); else if (svd.m_computeThinV) m_workspace.resize(svd.rows());

View File

@ -535,8 +535,8 @@ public:
while(++m_outerPos<m_end) while(++m_outerPos<m_end)
{ {
// Restart iterator at the next inner-vector: // Restart iterator at the next inner-vector:
m_it.~EvalIterator(); internal::destroy_at(&m_it);
::new (&m_it) EvalIterator(m_eval.m_argImpl, m_outerPos); internal::construct_at(&m_it, m_eval.m_argImpl, m_outerPos);
// search for the key m_innerIndex in the current outer-vector // search for the key m_innerIndex in the current outer-vector
while(m_it && m_it.index() < m_innerIndex) ++m_it; while(m_it && m_it.index() < m_innerIndex) ++m_it;
if(m_it && m_it.index()==m_innerIndex) break; if(m_it && m_it.index()==m_innerIndex) break;

View File

@ -109,7 +109,7 @@ struct product_evaluator<Product<Lhs, Rhs, AliasFreeProduct>, ProductTag, Permut
explicit product_evaluator(const XprType& xpr) explicit product_evaluator(const XprType& xpr)
: m_result(xpr.rows(), xpr.cols()) : m_result(xpr.rows(), xpr.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
generic_product_impl<Lhs, Rhs, PermutationShape, SparseShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs()); generic_product_impl<Lhs, Rhs, PermutationShape, SparseShape, ProductTag>::evalTo(m_result, xpr.lhs(), xpr.rhs());
} }

View File

@ -149,7 +149,7 @@ struct unary_evaluator<SparseView<Product<Lhs, Rhs, Options> >, IteratorBased>
: m_result(xpr.rows(), xpr.cols()) : m_result(xpr.rows(), xpr.cols())
{ {
using std::abs; using std::abs;
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
typedef typename nested_eval<Lhs,Dynamic>::type LhsNested; typedef typename nested_eval<Lhs,Dynamic>::type LhsNested;
typedef typename nested_eval<Rhs,Dynamic>::type RhsNested; typedef typename nested_eval<Rhs,Dynamic>::type RhsNested;
LhsNested lhsNested(xpr.nestedExpression().lhs()); LhsNested lhsNested(xpr.nestedExpression().lhs());

View File

@ -100,9 +100,9 @@ protected:
void construct(Expression& expr) void construct(Expression& expr)
{ {
if(expr.outerIndexPtr()==0) if(expr.outerIndexPtr()==0)
::new (static_cast<Base*>(this)) Base(expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr()); internal::construct_at<Base>(this, expr.size(), expr.nonZeros(), expr.innerIndexPtr(), expr.valuePtr());
else else
::new (static_cast<Base*>(this)) Base(expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(), expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr()); internal::construct_at<Base>(this, expr.rows(), expr.cols(), expr.nonZeros(), expr.outerIndexPtr(), expr.innerIndexPtr(), expr.valuePtr(), expr.innerNonZeroPtr());
} }
}; };
@ -203,8 +203,7 @@ class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType
~Ref() { ~Ref() {
if(m_hasCopy) { if(m_hasCopy) {
TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(&m_storage); internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
obj->~TPlainObjectType();
} }
} }
@ -215,8 +214,7 @@ class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType
{ {
if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed())) if((Options & int(StandardCompressedFormat)) && (!expr.isCompressed()))
{ {
TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(&m_storage); TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
::new (obj) TPlainObjectType(expr);
m_hasCopy = true; m_hasCopy = true;
Base::construct(*obj); Base::construct(*obj);
} }
@ -229,8 +227,7 @@ class Ref<const SparseMatrix<MatScalar,MatOptions,MatIndex>, Options, StrideType
template<typename Expression> template<typename Expression>
void construct(const Expression& expr, internal::false_type) void construct(const Expression& expr, internal::false_type)
{ {
TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(&m_storage); TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
::new (obj) TPlainObjectType(expr);
m_hasCopy = true; m_hasCopy = true;
Base::construct(*obj); Base::construct(*obj);
} }
@ -321,8 +318,7 @@ class Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType
~Ref() { ~Ref() {
if(m_hasCopy) { if(m_hasCopy) {
TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(&m_storage); internal::destroy_at(reinterpret_cast<TPlainObjectType*>(&m_storage));
obj->~TPlainObjectType();
} }
} }
@ -337,8 +333,7 @@ class Ref<const SparseVector<MatScalar,MatOptions,MatIndex>, Options, StrideType
template<typename Expression> template<typename Expression>
void construct(const Expression& expr, internal::false_type) void construct(const Expression& expr, internal::false_type)
{ {
TPlainObjectType* obj = reinterpret_cast<TPlainObjectType*>(&m_storage); TPlainObjectType* obj = internal::construct_at(reinterpret_cast<TPlainObjectType*>(&m_storage), expr);
::new (obj) TPlainObjectType(expr);
m_hasCopy = true; m_hasCopy = true;
Base::construct(*obj); Base::construct(*obj);
} }

View File

@ -383,7 +383,7 @@ struct product_evaluator<Product<LhsView, Rhs, DefaultProduct>, ProductTag, Spar
product_evaluator(const XprType& xpr) product_evaluator(const XprType& xpr)
: m_lhs(xpr.lhs()), m_result(xpr.rows(), xpr.cols()) : m_lhs(xpr.lhs()), m_result(xpr.rows(), xpr.cols())
{ {
::new (static_cast<Base*>(this)) Base(m_result); internal::construct_at<Base>(this, m_result);
generic_product_impl<typename Rhs::PlainObject, Rhs, SparseShape, SparseShape, ProductTag>::evalTo(m_result, m_lhs, xpr.rhs()); generic_product_impl<typename Rhs::PlainObject, Rhs, SparseShape, SparseShape, ProductTag>::evalTo(m_result, m_lhs, xpr.rhs());
} }

View File

@ -531,16 +531,16 @@ class UmfPackLU : public SparseSolverBase<UmfPackLU<MatrixType_> >
template<typename MatrixDerived> template<typename MatrixDerived>
void grab(const EigenBase<MatrixDerived> &A) void grab(const EigenBase<MatrixDerived> &A)
{ {
mp_matrix.~UmfpackMatrixRef(); internal::destroy_at(&mp_matrix);
::new (&mp_matrix) UmfpackMatrixRef(A.derived()); internal::construct_at(&mp_matrix, A.derived());
} }
void grab(const UmfpackMatrixRef &A) void grab(const UmfpackMatrixRef &A)
{ {
if(&(A.derived()) != &mp_matrix) if(&(A.derived()) != &mp_matrix)
{ {
mp_matrix.~UmfpackMatrixRef(); internal::destroy_at(&mp_matrix);
::new (&mp_matrix) UmfpackMatrixRef(A); internal::construct_at(&mp_matrix, A);
} }
} }