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)
: 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
EIGEN_DEVICE_FUNC evaluator(const ArgType& arg)
: m_result(arg)
{
::new (static_cast<Base*>(this)) Base(m_result);
internal::construct_at<Base>(this, m_result);
}
protected:

View File

@@ -104,7 +104,7 @@ struct unary_evaluator<Inverse<ArgType> >
unary_evaluator(const InverseType& inv_xpr)
: 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);
}

View File

@@ -109,7 +109,7 @@ struct product_evaluator<Product<Lhs, Rhs, Options>, ProductTag, LhsShape, RhsSh
explicit product_evaluator(const XprType& xpr)
: 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?,
// 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;
}
::new (static_cast<Base*>(this)) Base(expr.data(), rows, cols);
::new (&m_stride) StrideBase(
internal::construct_at<Base>(this, expr.data(), rows, cols);
internal::construct_at(&m_stride,
(StrideType::OuterStrideAtCompileTime == 0) ? 0 : outer_stride,
(StrideType::InnerStrideAtCompileTime == 0) ? 0 : inner_stride );
return true;

View File

@@ -106,7 +106,7 @@ struct evaluator<ReturnByValue<Derived> >
EIGEN_DEVICE_FUNC explicit evaluator(const XprType& xpr)
: 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);
}

View File

@@ -125,7 +125,7 @@ struct evaluator<Solve<Decomposition,RhsType> >
EIGEN_DEVICE_FUNC explicit evaluator(const SolveType& solve)
: 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);
}

View File

@@ -1150,6 +1150,38 @@ inline int queryTopLevelCacheSize()
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 Eigen