How to overload array index operator for wrapper class of 2D array?
The easier solution is to use the operator() as it allows multiple parameters.
class M
{
public:
int& operator()(int x,int y) {return at(x,y);}
// .. Stuff to hold data and implement at()
};
M a;
a(1,2) = 4;
The easy way is that the first operator[] returns an intermediate object that the second operator[] returns the value from the array.
class M
{
public:
class R
{
private:
friend class M; // Only M can create these objects.
R(M& parent,int row): m_parent(parent),m_row(row) {}
public:
int& operator[](int col) {return m_parent.at(m_row,col);}
private:
M& m_parent;
int m_row;
};
R operator[](int row) {return R(*this,row);}
// .. Stuff to hold data and implement at()
};
M b;
b[1][2] = 3; // This is shorthand for:
R row = b[1];
int& val = row[2];
val = 3;
Operator[][] overload
You can overload operator[]
to return an object on which you can use operator[]
again to get a result.
class ArrayOfArrays {
public:
ArrayOfArrays() {
_arrayofarrays = new int*[10];
for(int i = 0; i < 10; ++i)
_arrayofarrays[i] = new int[10];
}
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;
};
Then you can use it like:
ArrayOfArrays aoa;
aoa[3][5];
This is just a simple example, you'd want to add a bunch of bounds checking and stuff, but you get the idea.
How do create an overloaded operator for the form a[x][y]?
Here's a nice base implementation that does exactly what you want.
Update (September 26, 2013): I have improved the code quite a lot.
The type T
in the template only needs to satisfy the requirements of an std::vector
.
#include <vector>
#include <stdexcept>
template<typename T>
class matrix {
class row {
std::vector<T> values;
public:
row(std::size_t n)
: values(n, T()) {}
T& operator[] (std::size_t index) {
if (index < values.size())
return values[index];
else
throw std::domain_error("Matrix column index out of bounds.");
}
const T& operator[] (std::size_t index) const {
if (index < values.size())
return values[index];
else
throw std::domain_error("Matrix column index out of bounds.");
}
std::size_t size() const { return values.size(); }
};
std::vector<row> rows;
public:
matrix(std::size_t m, std::size_t n)
: rows(m, row(n)) {}
row& operator[](std::size_t index) {
if (index < rows.size())
return rows[index];
else
throw std::domain_error("Matrix row index out of bounds.");
}
const row& operator[](std::size_t index) const {
if (index < rows.size())
return rows[index];
else
throw std::domain_error("Matrix row index out of bounds.");
}
std::size_t row_count() const { return rows.size(); }
std::size_t col_count() const {
if (rows.size()) return rows[0].size();
return 0;
}
std::size_t size() const { return row_count() * col_count(); }
};
For convenience, this helper can be used to print a matrix.
#include <ostream>
template<typename T>
std::ostream& operator <<(std::ostream& o, const matrix<T>& mat) {
for (std::size_t i = 0u; i < mat.row_count(); ++i) {
for (std::size_t j = 0u; j < mat.col_count(); ++j) {
o << mat[i][j] << ' ';
}
o << '\n';
}
return o;
}
And just for you, a usage example to test this:
int main() {
matrix<int> mat_0(2, 3);
matrix<double> mat_1(1, 2);
mat_0[0][0] = 2;
mat_0[0][1] = 3;
mat_0[0][2] = 4;
mat_0[1][0] = 3;
mat_0[1][1] = 7;
mat_0[1][2] = 9;
mat_1[0][0] = 0.43;
mat_1[0][1] = 213.01;
std::cout << mat_0;
std::cout << '\n';
std::cout << mat_1;
return 0;
}
Overload = operator for class that shall behave like matrix
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.
Overloading the [] operator in python class to refer to a numpy.array data member
You need to implement the __getitem__
and __setitem__
magic functions.
A complete overview for the magic methods can be found here.
import numpy as np
class MyArray():
def __init__(self):
self.data = np.zeros(10)
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
def __repr__(self):
return 'MyArray({})'.format(self.data)
a = MyArray()
print(a[9])
print(a[1:5])
a[:] = np.arange(10)
print(a)
Which will give you this result:
0.0
[ 0. 0. 0. 0.]
MyArray([ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.])
Inheritance
If you just want to modify or add behaviour of np.ndarray, you could inherit from it. This is a little more complicated than for normal python classes, but implementing your case should be not that hard:
import numpy as np
class MyArray(np.ndarray):
def __new__(cls, shape, fill_value=0, dtype=float):
data = np.full(shape, fill_value, dtype)
obj = np.asarray(data).view(cls)
obj.fill_value = fill_value
return obj
def reset(self, fill_value=None):
if fill_value is not None:
self.fill_value = fill_value
self.fill(self.fill_value)
For more info, see here.
How can I invoke an overloaded () operator on the keyword this?
You have a few options:
(*this)(5)
this->operator()(5)
or just
operator()(5)
Create a method that you call from within the
operator()
, e.g.:void do_work(int a) { /* ... */ }
void operator()(int a) { do_work(a); }
void myFunc() { do_work(5); }
Whichever you choose is just a matter of personal taste.
Just for fun, here are some more (ridiculous) options:
std::invoke
(mentioned in comments):std::invoke(&MyStruct::operator(), this, 5);
mem_fn
:auto call_op = std::mem_fn(&MyStruct::operator());
call_op(this, 5);lambda:
auto call_op = [this] (int a) { operator()(a); };
call_op(5);bind_front
auto call_op = std::bind_front(&MyStruct::operator(), this);
call_op(5);
Overloading subscript operator and working with double-pointers?
It's not clear why you are using double indirection in the first place.
If pixels
is a double pointer to an array of pixels, you can do
pixels& MyWrapper::operator[] (const int nIndex) {
return (*Image.pixels)[nIndex]; // where Image is of type image
}
If pixels
is a pointer to an array of pointers to arrays, then you need two indices:
pixels& MyWrapper::operator() ( int xIndex, int yIndex ) {
return Image.pixels[yIndex][xIndex]; // where Image is of type image
}
There are a few weird things going on here.
typedef class { } identifier
is not good C++. Useclass identifier { };
, or else the class has no name, so you cannot define member functions outside theclass { }
scope. (Among other problems.)- There is no reason to make a parameter type
const int
. Plainint
accomplishes the same thing. - There is no apparent reason for the double indirection. Typically in C++ we avoid the direct use of pointers. There is probably a prepackaged standard structure you can use instead.
dynamical two dimension array according to input
Boost implements matrices (supporting mathematical operations) in its uBLAS library, and provides usage syntax like the following.
#include <boost/numeric/ublas/matrix.hpp>
int main(int argc, char* argv[])
{
unsigned int N = atoi(argv[1]);
boost::matrix<int> myMatrix(N, N);
for (unsigned i = 0; i < myMatrix.size1 (); ++i)
for (unsigned j = 0; j < myMatrix.size2 (); ++j)
myMatrix(i, j) = 3 * i + j;
return 0;
}
Related Topics
C++ -- How to Overload Operator+=
Boost.Python Call by Reference:Typeerror: No To_Python (By-Value) Converter Found for C++ Type:
Is It Allowed to Cast Away Const on a Const-Defined Object as Long as It Is Not Actually Modified
What Are the Differences Between Std::Variant and Boost::Variant
Three Forward Slashes for Block Commenting
Is Constexpr a "Hint" (Like Inline) or "A Binding Request" to the Compiler
How to Increase Error Limit in Visual Studio
Problem with Compiling Rinside Examples Under Windows
How to Vertically Align Text in Edit Box
Stl Container with Std::Unique_Ptr's VS Boost::Ptr_Container
Std::Vector Calling Destructor Multiple Times During Push_Back
Stl Algorithms: Why No Additional Interface for Containers (Additional to Iterator Pairs)
Expand MACro Inside String Literal
How to Get the Starting/Base Address of a Process in C++
How to Get the Address of the Std::Vector Buffer Start Most Elegantly