Re: [eigen] Why do const accessors return by value? |

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

*To*: eigen@xxxxxxxxxxxxxxxxxxx*Subject*: Re: [eigen] Why do const accessors return by value?*From*: Patrick Mihelich <patrick.mihelich@xxxxxxxxx>*Date*: Tue, 31 Mar 2009 14:43:01 -0700*Dkim-signature*: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:in-reply-to:references :date:message-id:subject:from:to:content-type; bh=HLWQgNjjj6e/uy2wJACiZUOW74wZSy5VowLN71o2dYo=; b=bd0rpFwDkxizyr0OeJJJ113yDoSxxW+wrRVjG/SyJLvBZp1xhghyqUlfy6qmYZZ1M5 GdGIe14vE4e0NTaB5Jh0OtXqZn42TWloyN4Q8T0fxAQWvbJsx8QMuOgM3M4e6zKZvQ9d Jizph9iJLhaDpuO+uQLv1VaIcRjQMAAv8kwbA=*Domainkey-signature*: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; b=vJlESiWLzx83oqzB5r/tXtKlIMCiAjTDKxJWwenY+uPSFuXsSAYhUxRqid14+UWQG8 mvIUOyvKofPHPrwiQT71MftSXuIPrsN1IGt8VLEtsvMENx7+E63kbnKqPvsVPwNgemAN qqpQCEqRq0261LNaEIx7AKlmlRcIyRjU8wKzo=

On Tue, Mar 31, 2009 at 1:04 PM, Benoit Jacob <jacob.benoit.1@xxxxxxxxx> wrote:

2009/3/31 Patrick Mihelich <patrick.mihelich@xxxxxxxxx>:

> Hi again,Yes, in fact we have simply no choice. A MatrixBase may be any

>

> Currently all of the MatrixBase const accessor functions return const

> Scalar, while the non-const version return (of course) Scalar&. Is there a

> rationale for returning by value in the const versions instead of const

> Scalar&?

_expression_. As soon as an _expression_ represents a nontrivial

computation (like a sum of two matrices) there is no way that coeff()

could return a reference : a reference to what? the result isn't

stored permanently in memory.

OK, right. But you do not always have to use the lowest-common-denominator behavior (return by value). MatrixBase knows the Derived type and can return by const-reference for Derived types with dense storage (Matrix, Map).

The "standard C++" approach is to give MatrixBase three typedefs: value_type, reference (return type of non-const accessors, convertible to value_type), and const_reference (return type of const accessors, convertible to value_type); then use these to define your accessors. STL/Boost users will recognize these names but you could certainly use friendlier ones like Scalar, ScalarRef, and ScalarConstRef:

ScalarRef operator() (int index);

ScalarConstRef operator() (int index) const;

ScalarRef operator() (int row, int col);

ScalarConstRef operator() (int row, int col) const;

//etc.

For dense storage types:

typedef Scalar& ScalarRef;

typedef const Scalar& ScalarConstRef;

For _expression_ types:

typedef Scalar ScalarRef;

typedef Scalar ScalarConstRef;

> I don't like this inconsistent behavior. Sometimes I want to get a> pointer to a chunk of memory in a Matrix so I can pass it to some low-levelAbove you were talking about MatrixBase; now with Matrix it's

> function, like foo( &mat(r, c) ).

different, indeed the coefficients do exist in memory, and if you look

at the Matrix class, the coeff() methods do return const references,

exactly like you want!

If you have a MatrixBase that happens to be a Matrix, you can always

use the derived() method to get the matrix:

void foo(const MatrixBase& m)

{

float *ptr = &(m.derived().coeff(i,j));

}

in fact derived() just casts 'this' to a Matrix pointer, and indirects.

OK but this is more verbose, and it's rather surprising that it doesn't do the same thing as m(i,j) or even m.coeff(i,j). I do not think Matrix should override the coeff() methods from MatrixBase with different signatures; more generally I'd suggest that for any MatrixBase method foo, m.foo() and m.derived().foo() should always behave identically.

BTW, there is a mistake in MapBase: const Scalar coeff(int index) const should return const Scalar&.

That's another issue. But the above-mentioned fact that xpressions

> This breaks when mat is a const type like

> const Matrix&. I can also imagine wanting to use Eigen matrices with types

> that are not trivially cheap to copy (arbitrary precision types, for

> example), when returning by value may result in an unwanted copy.

have no choice but to return by value, is unavoidable. So I think that

the best solution then, is that the "heavy numeric types" in question

be endowed with a copy-on-write mechanism so that these copies become

shallow copies.

Making the accessor return types smarter I think is much simpler.

Cheers,

Patrick

**Follow-Ups**:**Re: [eigen] Why do const accessors return by value?***From:*Benoit Jacob

**References**:**[eigen] Why do const accessors return by value?***From:*Patrick Mihelich

**Re: [eigen] Why do const accessors return by value?***From:*Benoit Jacob

**Messages sorted by:**[ date | thread ]- Prev by Date:
**Re: [eigen] Why do const accessors return by value?** - Next by Date:
**Re: [eigen] Why do const accessors return by value?** - Previous by thread:
**Re: [eigen] Why do const accessors return by value?** - Next by thread:
**Re: [eigen] Why do const accessors return by value?**

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