This question already has answers here:
C++ overloading array operator
(3 answers)
Closed 2 years ago.
I'm having some troubles trying to understand the following.
While writing a simple Matrix class with vector and templates I tried to overload the [] operator to acces the elements. This is the class
#pragma once
#include <vector>
#include <iostream>
template <typename T>
class Matrix
{
private:
std::vector<std::vector<T>> values;
int rows, cols;
public:
Matrix(int row, int col) : rows(row), cols(col) {
values = std::vector<std::vector<T>>(rows, std::vector<T>(cols));
}
std::vector<T>& operator[] (const int i) const{
return values[i];
}
};
Note that I'm returning a vector<T>, so I can use the double indexing easily.
The problem I'm having is that , when trying to call the operator, there is the following error:
Cannot realize the conversion from 'const_Ty' to 'std::vector<T,std::allocator<T>> &
And I have no clue where this conversion is happening. I'm not modifying anything from the class, so I thought I should use const.
The method being const means that the member variables are treated as const and can’t be modified.
You’re currently returning a std::vector<T>& which means a caller could modify it (but that goes against the const qualifier).
Change the return type to const std::vector<T>&, so that callers can’t modify the returned value.
Related
I am trying to develop a custom class in C++ which would contain a mpfr_t array.
The problem is, I do not know how to overload the [] operator to access array elements.
See the code below:
template <const unsigned int N>
class MyClass<mpfr_t, N> {
private:
mpfr_t array[N];
public:
mpfr_t& operator[] (const unsigned int i) const {
assert(0 <= i && i < N);
return array[i];
The problem with the code above is that I cannot use const and return a reference; as this would allow for potential value modification. What is usually done in such cases is that people write two versions of []: one const for constant class instances returning a value (not a reference) and another non-const which returns the reference. However, I cannot return mpfr_t type - this is simply not allowed by the library design:
error: function cannot return array type 'mpfr_t' (aka '__mpfr_struct [1]')
I realise that the problem stems from wrapping a C-dedicated code into strictly C++ mechanism of operator overloading, but I wonder if there is any hack around it?
You can implement the const version of operator[] by returning a const reference, instead of a non-const one (as you do in the current version):
//-----vvvvvvv-----------------------------------vvvvv--
mpfr_t const & operator[] (const unsigned int i) const {
assert(0 <= i && i < N);
return array[i];
}
Note that you can still have the non-const overload as well:
mpfr_t & operator[] (const unsigned int i) {
// ...
The first overload will be chosen if your MyClass object is const.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm learning C++ Expression Templates these days, I've read a lot of articles. Still confused about how to design an express template.
Is there any standard way(steps) when we design Expression Templates, in other words , how to design, including what classes should I create and what operations should I performed in specific functions?
Let's say Matrix computations.
I know how to write it via overloading C++ operators, but after I finish it by overloading coperators I don't know how to write it using Expression Templates.
The main idea of having an expression template is to use lazy evaluation, i.e. only compute result when using an expression that uses the addition, subtraction, etc. expression for specific index, instead of computing the result for all the values of the arrays in the constructor.
Have a "sum" class with two variable members, where each represent the arrays that you want to add (As you add more than two arrays, this class will be used "recursively" as I'll show below). For this you need to have a class with 2 template arguments for each member, and have an operator[] which returns the addition of both arrays for specific location, i.e.
int operator[](const int i) const
{
return a[i] + b[i];
}
Have a "starting" class which initializes the values of your arrays. Note that this class is different from the above, as it will only store 1 array. Also this class must implement operator[] as follows:
int operator[](const int i) const
{
return starting_vector[i];
}
Have an overload operator+ to add your "starting" vector (from 2 bullet) with other ones, and to store them in the "sum" class (from 1 bullet) as:
template <typename A, typename B>
VectorSum<A, B> operator+(const A v1, const B v2)
{
return VectorSum<A, B>{v1, v2};
}
Below is a complete example that compiles:
#include <initializer_list>
#include <iostream>
#include <stdexcept>
#include <vector>
class Vector
{
public:
explicit Vector(const std::initializer_list<int>& vec)
{
for (const auto x : vec)
{
starting_vector.push_back(x);
}
}
int operator[](const int i) const
{
return starting_vector[i];
}
std::size_t size() const
{
return starting_vector.size();
}
private:
std::vector<int> starting_vector;
};
template <typename A, typename B>
class VectorSum
{
public:
VectorSum(const A& other_a, const B& other_b):
a{other_a}, b{other_b}
{
if (other_a.size() != other_b.size())
{
throw std::invalid_argument{"must be same sizes"};
}
}
int operator[](const int i) const
{
return a[i] + b[i];
}
std::size_t size() const
{
return a.size();
}
private:
const A a;
const B b;
};
template <typename A, typename B>
VectorSum<A, B> operator+(const A v1, const B v2)
{
return VectorSum<A, B>{v1, v2};
}
int main()
{
Vector v1{{1,2,3,4,100}};
Vector v2{{1,2,3,4,1}};
Vector v3{{1,2,3,4,2}};
Vector v4{{1,2,3,10,5}};
VectorSum<VectorSum<VectorSum<Vector, Vector>, Vector>, Vector> sum {v1 + v2 + v3 + v4};
std::cout << sum[0] << std::endl;
}
This question already has answers here:
C++ overload operator [ ][ ]
(7 answers)
Closed 5 years ago.
as an exercise i got to implamant a operator[][] to a matrix class. The compiler makes problems and does not let me even start. does anyone have any iddea why?
template <class Type>
Type Matrix<Type>::operator[][](int i, int j)
{
return getElement(i, j);
}
the method need to return the place [row][col] in the matrix.
thanks
There is no operator[][] in C++. The easiest way to achieve what you want is to resort to operator():
template <class Type>
Type Matrix<Type>::operator()(int i, int j)
{
return getElement(i, j);
}
If you want to make your life harder, you can use a workaround by overloading operator[] such that it returns a proxy object which also overloads operator[]. For the caller, the chained operator[] calls will work as if there was an operator[][].
As the other answer suggested you can do it with a function but if you really want to do this you will need to return an object from the operator[] of the matrix and then this object will need an operator[] which will return the type. Example:
template <class Type>
class Matrix {
public:
class Row{
public:
Type operator[](int col) {
}
};
Row operator[](int row) {
}
};
...
Matrix<int> m;
m[1][2];
This question already has answers here:
C++: Overloading the [ ] operator for read and write access
(3 answers)
Closed 7 years ago.
I'm currently attempting to overload the '[]' operator for both read and write operations. I have created them like the following:
V operator[] (K key) const; //Read
V& operator[] (K key); //Write
However, only the 'write' is called from both the following:
foo["test"] = "bar"; //Correct, will use 'write'
cout << foo["test"]; //Incorrect, will use 'write'
What is the reason for this and is there a possible solution?
Same question that didn't help, found here: C++: Overloading the [ ] operator for read and write access
Although, the solution presented did not work as intended, and still only the write overload was accessed.
Overloading is done based on the static type of the argument. If the object foo you use an operator with is non-const the non-const overload is used. If it is const the const overload is used.
If you want to distinguish between reading and writing you'll need to return a proxy from your subscript operator which converts to the suitable type for reading and has a suitable assignment operator for writing:
class X;
class Proxy {
X* object;
Key key;
public:
Proxy(X* object, Key key): object(object), key(key) {}
operator V() const { return object->read(key); }
void operator=(V const& v) { object->write(key, v); }
};
class X {
// ...
public:
V read(key) const;
void write(key, V const& v);
Proxy operator[](Key key) { return Proxy(this, key); }
V operator[](Key key) const { return this->read(key); }
// ...
};
This question already has answers here:
How to overload array index operator for wrapper class of 2D array? [duplicate]
(2 answers)
Closed 9 years ago.
I've got a template of a class that shall behave like matrix.
So the usecase is something like:
Matrix matrix(10,10);
matrix[0][0]=4;
//set the values for the rest of the matrix
cout<<matrix[1][2]<<endl;
When I set the values directly in the constructor, it works well, but when I want to use matrix[x][y]=z; I get error: lvalue required as left operand of assignment. I assume, that I must overload = operator. Nevertheless I tried whole evening and I didn't find out, how to implement it. Would anybody be please so kind and show me how to overload = operator for my code, to make it assign values to that matrix?
code:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <sstream>
using namespace std;
class Matrix {
public:
Matrix(int x,int y) {
_arrayofarrays = new int*[x];
for (int i = 0; i < x; ++i)
_arrayofarrays[i] = new int[y];
// works here
_arrayofarrays[3][4] = 5;
}
class Proxy {
public:
Proxy(int* _array) : _array(_array) {
}
int operator[](int index) {
return _array[index];
}
private:
int* _array;
};
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
private:
int** _arrayofarrays;
};
int main() {
Matrix matrix(5,5);
// doesn't work :-S
// matrix[2][1]=0;
cout << matrix[3][4] << endl;
}
If you intend to modify the element of the matrix referenced by the proxy, then the overload of operator[] in the Proxy class must return a reference:
int& operator[](int index)
At the moment, you return int, which makes a copy of the element’s value—not what you want. There ought to be a const overload as well, so that operator[] works on const matrices. This one can return by value:
int operator[](int index) const
And actually, size_t would be more appropriate for the index than int, since it’s an unsigned type. You aren’t giving any particular meaning to negative indices, so it makes sense to disallow them.
You don’t need to overload operator= of Proxy unless you want to assign a whole row at once. In fact, you don’t need the Proxy class at all, because you can just return a pointer to the row array directly. However, if you want to change your design—e.g., using a sparse or packed representation—then the Proxy would let you keep the m[i][j] interface.
The issue is that you're returning an int value in proxy::operator[]. Your first [] operator returns the proxy object, the second returns an int. If your proxy [] operator were to return an int reference, then you would be able to assign to it:
int& operator[](int index) {
return _array[index];
}