Re: [eigen] Passing result of block() as non-const reference-to-matrix?

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]


Yes, this is an ugly issue with expression templates. As you said, the
cleanest way is to use rvalue references.

A second option is to define the function as

template <typename Derived>
void incrementBottomRight(const Eigen::MatrixBase<Derived>& m)

and const_cast to "Eigen::MatrixBase<Derived>&" -- as I said, ugly.
The third an most portable option is in fact to call the function like
this:

Eigen::Block<MatrixXd> b = m.testMatrix.block(0, 0, 2, 2); // this has
quasi zero cost
incrementBottomRight(b);

But in case you have access to them rvalue references are the best option here.

Cheers,
Hauke

On Fri, Jul 9, 2010 at 12:01 PM, Martin Senst <martin.senst@xxxxxx> wrote:
> Hi everyone,
>
> a second problem is that the result of testMatrix.block(0, 0, 2, 2) is a
> temporary object which cannot be bound to an lvalue reference. I'm not sure
> how to circumvent this problem in C++ 03, but if you are using C++0x, you can
> define a second function which takes an rvalue reference. The following
> program works with g++ 4.5 and -std=c++0x, and outputs
>
> 0 0 0
> 0 1 0
> 0 0 1
>
>
> Cheers,
> Martin
>
>
>
>
> #include <Eigen/Core>
>
> template <typename Derived>
> void incrementBottomRight(Eigen::MatrixBase<Derived>& m)
> {
>    m(m.rows() - 1, m.cols() - 1) += 1.0;
> }
>
>
> template <typename Derived>
> void incrementBottomRight(Eigen::MatrixBase<Derived>&& m)
> {
>    m(m.rows() - 1, m.cols() - 1) += 1.0;
> }
>
>
> int main()
> {
>    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> testMatrix(3, 3);
>
>    testMatrix.setZero();
>
>    // This uses the first version with an lvalue-reference parameter
>    incrementBottomRight(testMatrix);
>
>    // This uses the second version with an rvalue-reference parameter
>    incrementBottomRight(testMatrix.block(0, 0, 2, 2));
>
>    std::cout << testMatrix << std::endl;
>
>    return 0;
> }
>
>
>
>
> Am Freitag 09 Juli 2010, 11:52:52 schrieb Hauke Heibel:
>> Hi Sidney,
>>
>> that is expected since a matrix block is not a matrix. It is a special
>> matrix expression which shares operations defined in MatrixBase and
>> DenseBase with matrices. So you need to declare your function as a
>> template function like this
>>
>> template <typename Derived>
>> void incrementBottomRight(Eigen::MatrixBase<Derived> & m)
>> {
>>    m(m.rows() - 1, m.cols() - 1) += 1.0;
>> }
>>
>> In case this is not an option you could probably do
>>
>> void incrementBottomRight(Eigen::Block<MatrixXd> & m)
>> {
>>    m(m.rows() - 1, m.cols() - 1) += 1.0;
>> }
>>
>> but then the function will be limited to blocks only.
>>
>> Regards,
>> Hauke
>>
>> On Fri, Jul 9, 2010 at 11:28 AM, Sidney Cadot <sidney.cadot@xxxxxxxxx>
> wrote:
>> > Hello,
>> >
>> > Today I found, to my surprise, that passing the result of a
>> > Matrix::block() method to a function that takes a reference to an
>> > Eigen::Matrix doesn't seem to work. The program (which doesn't compile)
>> > demonstrates the problem.
>> >
>> > I know that it /is/ possible to pass the result of a Matrix::block()
>> > const call to a const reference to an Eigen::Matrix. Is it intentional
>> > that the non-const version of this does not work?
>> >
>> > Any help would be greatly appreciated.
>> >
>> > Regards, Sidney
>> >
>> > /////////////////////// code fragment starts here
>> >
>> > #include <Eigen/Core>
>> >
>> > void incrementBottomRight(Eigen::Matrix<double, Eigen::Dynamic,
>> > Eigen::Dynamic> & m) {
>> >    m(m.rows() - 1, m.cols() - 1) += 1.0;
>> > }
>> >
>> > int main()
>> > {
>> >    Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> testMatrix(3,
>> > 3);
>> >
>> >    // This works fine
>> >    incrementBottomRight(testMatrix);
>> >
>> >    // This gives a compiler error
>> >    incrementBottomRight(testMatrix.block(0, 0, 2, 2));
>> >
>> >    std::cout << testMatrix << std::endl;
>> >
>> >    return 0;
>> > }
>
>
>
>



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/