Reputation: 1544
I have a (data/storage) class with a member arma::mat
(a matrix), and I want to access just one column of this matrix (arma::colvec
), but I don't want to create a copy of the data in the column. Is there any way of achieving this?
My first try was using .col(i)
, but this returns a temporary, so taking a reference doesn't work.
Using .colptr(i)
doesn't create a copy, but it also returns a double*
instead of a vec
, so it makes my life a bit hard.
struct Data
{
mat A;
/* constructors etc. */
// reference to temporary (this is bad)
const vec& getColumn(const uint i) { return A.col(i); }
// doesn't create a copy, but doesn't return a vec either
const double* getColumn2(const uint i) const { return A.colptr(i); }
}
The reason for wanting this is that the class has both vectors and matrices, and I want to make uniform getter and setter methods that access either one of the vectors, or a column in a matrix, depending on an index (for iteration purposes).
An example:
struct Data
{
mat A;
vec b;
// getter
const vec& operator()(const uint i) const
{
if (i == 0)
{
return b;
}
else if (i == 1)
{
// return first column of A
}
// etc.
}
// setter
vec& operator()(const uint i)
{
// similar to above
}
}
Based on the answer by zauguin I found the following way to achieve the wanted functionality:
struct Data
{
mat A;
vec b;
// getter
subview_col<mat::elem_type> operator()(const uint i)
{
if (i == 0)
{
return b.col(0);
}
else if (i > 0 && i < (1 + A.n_cols()))
{
return A.col(i - 1);
}
else
{
// should probably do some error checking here
}
}
// setter
vec& operator()(const uint i)
{
// same as the above, but without consts in declaration
}
}
This returns subview_col<mat::elem_type>
instead of vec
, but the functionality is similar/identical for my purposes. I am not sure of the performance impact of using .col(0)
on a vec
, but I'm not that worried.
Upvotes: 3
Views: 2758
Reputation: 909
In arma, A.col(i) doesn't return a reference, but a temporary. You can return this temporary to get reference semantics. With C++14, just write
auto getColumn(const uint i) { return A.col(i); }
Otherwise, you have to return the proxy type, it is
subview_col<mat::elem_type> getColumn(const uint i) { return A.col(i); }
If you have to return a vec
instead of a subview_col<...>
, you can use A.unsafe_col(i)
, but you have to be sure, that you don't try to use it, after the lifetime of A
ended. see here
Upvotes: 2