Registered Member
|
Let A be some matrix:
MatrixXd A(3,3); A.col(1) can be accessed as a vector. A.col(1).segment(1,2) is no more vector. It's a block matrix expression, so can't be accessed as a vector. It's very convinient if it can be as the following example: #include <Eigen/Array> #include <Eigen/Core> #include <Eigen/LU> // import most common Eigen types USING_PART_OF_NAMESPACE_EIGEN void func(VectorXd& a) { a[1] = 3.0; } int main() { MatrixXd A(3,3); func(A.col(1).segment(1,2)); } Of course, it occurs error: as_vector.cpp: In function ‘int main()’: as_vector.cpp:18: error: invalid initialization of non-const reference of type ‘Eigen::VectorXd&’ from a temporary of type ‘Eigen::Block<Eigen::Block<Eigen::Matrix<double, 10000, 10000, 2, 10000, 10000>, 10000, 1, 1, 32>, 10000, 1, 1, 32>’ as_vector.cpp:10: error: in passing argument 1 of ‘void func(Eigen::VectorXd&)’ Is it possible by some additional idea? Thank you |
Moderator
|
hi,
note that m.col(i) also returns a Block expression, and so if you write: func(A.col(1)); then what happens is that the returned Block expression is copied to a VectorXd and so 1) you pay for an extra copy, and 2) you cannot modify the coefficients of A in func because what you have is copy of its coefficients. To this end you need to write your function func like this: template<typename Derived> void func(MatrixBase<Derived>& a) { ... } then func will accept any expressions inheriting MatrixBase. You can restrict it to vector expression using a static assert in the body of the function: EIGEN_STATIC_ASSERT_IS_VECTOR_AT_COMPILE_TIME(Derived); |
Registered Member
|
Thank you for your replying.
I changed my program to the following one. But the same error occured. Commenting out EIGEN_STATIC_ASSERT_IS_VECTOR_AT_COMPILE_TIME(Derived) produced additional errors. Thank you. #include <Eigen/Array> #include <Eigen/Core> #include <Eigen/LU> // import most common Eigen types USING_PART_OF_NAMESPACE_EIGEN using namespace std; template<typename Derived> void func(MatrixBase<Derived>& a) { //EIGEN_STATIC_ASSERT_IS_VECTOR_AT_COMPILE_TIME(Derived); a[1] = 3.0; } int main() { MatrixXd A(3,3); func(A.col(1)); // the error also occured in the case of // A.col(1).segment(1,2). // Only A is ok. } |
Registered Member
|
Here you hit a limitation of the C++ language: one can't take non-constant references to temporary objects. That's why it is inherent in the language specification that such a function can't compile.
Work-arounds include: - let it take a const reference and then const_cast (but the drawback is that constness isn't enforced anymore) - write overloads of your functions, one taking a VectorXd&, one taking BY VALUE the return type of segment()...
Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list! |
Registered Member
|
One way I saw this handled in another matrix library was to treat the thing that acted like the "block" class here was conceptually more like a pointer, so it could be const, but what it points to could still be modified. (like the difference between (const float *) and (float * const).
So, a constant reference to a 'block' just meant you could not modify its size/shape/location/memory/etc..., but you could still modify the coefficients. If you wanted to specify the block or matrix coefficients were unmodifiable, the underlying Scalar type needed to be const (like Block<Matrix<const Scalar,blah,blah> >). I guess that is a bit convoluted, but I'm wondering was that sort of thing ever considered for Eigen? I'm starting to port an application over to Eigen, and it's pretty cool so far, except I'm still hung up a bit on this aspect. |
Registered Member
|
Interesting, I can say that at least I didn't think about it.
It seems a bit strange to me that const would have the meaning that you suggest. We always considered the array of coefficients and the numbers of rows/columns on an equal footing, I never thought of hierarchising them wrt constness. Also, I always considered matrices as a generalisation of numbers, a 1x1 matrix should behave exactly like a Scalar, so already at that level the meaning of const was prescribed. Ah, also, for fixed-size matrices, the only member data is the array of coefficients, so you're basically proposing that const Matrix4f is exactly like Matrix4f. Finally, I wonder: wrt template instantiations, is TemplateClass<const T> equivalent to TemplateClass<T> ? I actually don't think so, otherwise it would be impossible to write meta_is_const. Assuming no, then your idea would result in 2x more template instantiations when evaluating rvalue expressions, which means longer compilation times and redundant binary code generated.
Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list! |
Registered Member
|
Yeah, good points. I thought maybe it could just work for something like the Block class, (like Block<const Matrix> vs. const Block<Matrix>) but I think in the end, it would just get weird and confusing.
|
Registered users: Bing [Bot], daret, Google [Bot], sandyvee, Sogou [Bot]