Re: [eigen] proposal for "clean" output arguments

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


Wow, this is a terrific idea. Most of the time it will be used on
Eigen objects so .output() will be good. For the relatively few cases
where the output is a scalar, i think that the global output() is a
good solution. Actually, at the moment I cant think of an example
where the output is not a Eigen object....?

Benoit


2009/8/18 Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:
> Hi all,
>
> here is a proposal to deal with functions having output (or inout)
> arguments. Currently the situation is quite a mess:
>
> 1 - some take non const references like
> TriangularView::solveInPlace(MatrixBase<T>&)
> 2 - some take pointers like LU::solve(const MatrixBase<T1>& B,
> MatrixBase<T2>* X)
> 3 - some take const references like MatrixBase<T1>::swap(const MatrixBase<T2>&)
>
> The main advantage of the solution 3 is that allows to use temporary
> proxies, e.g.:
>
> m.col(i).swap(m.col(j));
>
> The main advantage of solution 2 is that it makes it clear what is an output:
>
> m.lu().solve(b, &x);
>
> The respective drawbacks of each method are pretty obvious I won't
> enumerate them one more time...
>
> So what I propose is to add a trivial Output<T> class mimicking a
> reference T& that we'll be passed by value. Ok to make thing crystal
> clear here is such a Output class:
>
> template<typename T> class Output
> {
>  public:
>    Output(T& obj) : m_object(obj) { }
>    operator T&() { return m_object; }
>  protected:
>    T& m_object;
> };
>
> then we add a output() member function to AnyMatrixBase<> :
>
> Output<Derived> output() { return derived(); }
>
> then the function LU::solve(const MatrixBase<T1>& B, MatrixBase<T2>*
> X) can be rewritten:
>
> LU::solve(const MatrixBase<T1>& B, Output<T2> _x) {
>  T2& x(_x);
>  // use x
> }
>
> and the user sill call it like this:
>
> mat.lu().solve(b, xs.col(2).output());
>
> For in-out argument we can do the same with a InOut<T> class, and a
> AnyMatrixBase::inout() function.
>
> Unless I missed something, I think this solution has all the
> advantages that someone can expect:
> - it is more C++ than pointers,
> - it respects constness (unlike const references)
> - it allows to use temporary proxies returned by a function (unlike
> references and pointers)
> - it make it crystal clear what is an output and an in-out arguments
> when someone read a piece of code (unlike all other solutions)
>
> The only limitation I can see is how to extend this concept to scalar
> type arguments because we cannot have:
>
> double x;
> x.output()
>
> Note that if we don't make the ctor of Output explicit, then the
> following we'll work:
>
> void foo(Output<float> _x);
>
> float x;
> foo(x);
>
> If we want to enforce to have "output" next to x, one possibility is
> to add a global function output(T&) and make the ctor of Output
> explicit:
>
> float x;
> foo(output(x));
>
> Note that such a global function will only work on declared objects,
> and not on temporary proxies, that is why we really have to also have
> the output() function as a member of AnyMatrixBase...
>
> Of course, another drawback is more API changes...
>
> What do you think ?
>
> gael.
>
>
>



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