Reputation: 23498
In the class below, when I try to return std::valarray&
for operator []
it says: invalid initialization of std::valarray& from R-Value reference std::valarray
.
I'm using it like so:
int main()
{
Matrix<int> MM(4, 4);
for (int I = 0, K = 0; I < 4; ++I)
{
for (int J = 0; J < 4; ++J)
{
MM[I][J] = K++; //Assigning to it does nothing atm :S
}
}
for (int I = 0; I < 4; ++I)
{
for (int J = 0; J < 4; ++J)
{
std::cout<<MM[I][J]<<" "; //Prints random values :l
}
std::cout<<"\n";
}
}
and the class is as follows:
template<typename T>
class Matrix
{
private:
int Width, Height;
std::valarray<T> Elements;
static_assert(std::is_arithmetic<T>::value, "Argument T must be of arithmetic type.");
public:
Matrix(int Width, int Height);
Matrix(T* Data, int Width, int Height);
Matrix(T** Data, int Width, int Height);
std::valarray<T>& operator [](int Index);
const std::valarray<T>& operator [](int Index) const;
};
template<typename T>
Matrix<T>::Matrix(int Width, int Height) : Width(Width), Height(Height), Elements(Width * Height, 0) {}
template<typename T>
Matrix<T>::Matrix(T* Data, int Width, int Height) : Width(Width), Height(Height), Elements(Width * Height)
{
std::copy(Data, Data + (Width * Height), &Elements[0]);
}
template<typename T>
Matrix<T>::Matrix(T** Data, int Width, int Height) : Width(Width), Height(Height), Elements(Width * Height)
{
std::copy(Data[0], Data[0] + (Width * Height), &Elements[0]);
}
//ERROR below..
template<typename T>
std::valarray<T>& Matrix<T>::operator [](int Index)
{
return Elements[std::slice(Index * Width, Width, 1)];
}
template<typename T>
const std::valarray<T>& Matrix<T>::operator [](int Index) const
{
return Elements[std::slice(Index * Width, Width, 1)];
}
So my question is.. How can I overload the [] operator so I can get a single row or column so that I can index that and assign to it? I don't want to use the () subscript operator
.
Upvotes: 1
Views: 266
Reputation: 109119
In the non-const
operator[]
you have, this expression
return Elements[std::slice(Index * Width, Width, 1)];
This creates an std::slice_array<T>
object, which is an rvalue. You cannot bind this to an std::valarray<T>&
. The error can be fixed by changing the function to return a valarray
by value instead of by reference.
template<typename T>
std::valarray<T> Matrix<T>::operator [](int Index) // <-- return by value
{
return Elements[std::slice(Index * Width, Width, 1)];
}
Upvotes: 2