Ref<T const, ...> fails silently for all but the simplest stride types
Summary
Ref<T, Options, StrideType> supports specializations for arbitrary stride types. If T is constant, then Ref may be constructed from arbitrary expressions whose scalar types match the one of Ref. If e.g. the stride type of the passed expression does not match StrideType, then Ref copy-converts the expression into its member variable m_object, which Ref then tries to map instead of the expression's data. m_object is a plain Matrix or Array, thus storing contiguous memory. Ref simply constructs it using the number of rows and columns of the passed expression, independent of StrideType. This all works fine if it is possible to map the contiguous memory given StrideType (as with e.g. Ref's defaults InnerStride<1> / OuterStride<>), and it fails if not, which I assume to be the intended behaviour. However, while Eigen is full of static and run-time assertions, the success of mapping is not asserted, making such failures harder to find.
Environment
- Operating System : Windows
- Architecture : x64
- Eigen Version : 3.4.0
- Compiler Version : MSVC 19.29
- Compile Flags : default for debug-configurations
- Vector Extension : irrelevant
Minimal Example
#include <Eigen/Dense>
// It may be clear already at compile-time that mapping m_object will fail, as in:
{
using Mat = Eigen::MatrixXd;
using Ref = Eigen::Ref<const Mat, Eigen::Unaligned, Eigen::InnerStride<2>>;
Mat mat = Mat::Zero(6, 3);
// Should not compile due to a static assertion failure,
// while it just happens to result in an empty Ref, without triggering assertion failures at run-time, either:
Ref ref(mat);
}
{
using Mat = Eigen::Matrix<double, 6, 3>;
using Ref = Eigen::Ref<const Mat, Eigen::Unaligned, Eigen::OuterStride<4>>;
Mat mat = Mat::Zero(6, 3);
// results in a Ref with 6 rows and 3 columns,
Ref ref(mat);
// and in a read-access violation:
ref(0, 0);
}
// Or only at run-time, as in:
{
using Mat = Eigen::MatrixXd;
using Ref = Eigen::Ref<const Mat, Eigen::Unaligned, Eigen::OuterStride<4>>;
Mat mat = Mat::Zero(6, 3);
// Results in an empty Ref, without triggering assertion failures at run-time:
Ref ref(mat);
}
Steps to reproduce
- build and run the code above with EIGEN_STATIC_ASSERT and eigen_assert enabled.
What is the current bug behavior?
If the creation of Ref fails, then no assertion failures are triggered.
What is the expected correct behavior?
If the creation of Ref fails, then assertion failures are triggered - preferably already at compile time, as far as this is possible.
Anything else that might help
- I suggest to introduce into Ref an EIGEN_STATIC_ASSERT that fails if StrideType cannot map contiguous memory, resulting in a compile-time error.
- I suggest to introduce into Ref::construct(..., false_type) an eigen_assert that fails if Base::construct has failed.