I want to create an operator [] in the case of two dimensional vector. After searching, I have found that it's impossible to pass two arguments. How I can obtain the value of m_matrix[i][j] in the main?
relevant code:
class MyMatrix
{
public: // Methods
MyMatrix();
~MyMatrix();
int operator[] (int n);
private: // Attributes
int m_n;
int m_m;
std:: vector <std:: vector <int> > m_matrix;
};
int MyMatrix::operator[](int n, int m) // in the cpp
{
if (n>=0 && m>=0 && n<=m_n && m<=m_m)
{
return m_matrix[n-1][m-1];
}
else
{ cout<<"******************"<<endl;
cout<<"No valid index"<<endl;
cout<<"******************"<<endl;
return 0;
}
}
...
mat_test1[2][2]; // for example in the main
What's wrong with this?
To resume the comment, you may do:
class MyMatrix
{
public:
// Other methods
const std::vector<int>& operator[] (int m) const { return m_matrix.at(m); }
std::vector<int>& operator[] (int m) { return m_matrix.at(m); }
int operator () (int m, int n) const { return m_matrix.at(m).at(n); }
int& operator () (int m, int n) { return m_matrix.at(m).at(n); }
private:
std::vector<std::vector<int>> m_matrix;
};
Note: I used at instead of [] to use the check from vector and so it throws exception for out of bound access.
And then use it:
MyMatrix matrix(5, 4); // size of the matrix from constructor
matrix[0][1] = 42; // MyMatrix::operator [] followed by std::vector<int>::operator[]
matrix(2, 2) = 42; // MyMatrix::operator () (int, int);
Live example.
There are several ways, but in the end, they all come down to using a
proxy.
For various reasons, the usual implementation of a Matrix isn't
std::vector<std::vector<T>>, but simply std::vector<T>, with an
appropriate calculation of the index. In this case:
class Matrix
{
int myRows;
int myColumns;
std::vector<int> myData;
class Proxy
{
Matrix* myOwner;
int myRow;
public:
Proxy( Matrix* owner, int row )
: myOwner( owner )
, myRow( row )
{
}
int& operator[]( int column )
{
return myOwner->get( myRow, column );
}
};
public:
Matrix( int rows, int columns )
: myRows( rows )
, myColumns( columns )
, myData( rows * columns )
{
}
int& get( int row, int column )
{
assert( 0 <= row && row < myRows
&& 0 <= column && column < myColumns );
return myData[ row * myColumns + column ];
}
Proxy operator[]( int row ) { return Proxy( this, row ); }
};
In fact, you'll want a few more overloads (and possibly two proxies) to
handle const and non-const overloads. But this is the general pattern
for such things.
Be aware, too, that there are two conventions concerning such overloads.
One is to say that the [] returns a projection, and that the correct
solution for handling indexing into multi dimensional structures is to
overload operator() (which can be made to take an arbitrary number of
parameters). I personally prefer the [][] solution, but this
preference is not universal; a lot of people with a more mathematical
background prefer using ().
Related
Context
In a header-file matrix.h I defined a struct holding a matrix.
A special feature is a function inside this struct which allows for iterating over the rows and columns and apply a function to each iteration step. The idea is to not have to write that loop a thousand times.
template <class T>
struct Matrix{
T* matrix;
int columns, rows;
Matrix(int rows, int columns) : rows(rows), columns(columns)
matrix = new T[columns * rows];
}
template<typename Func>
void iterate_over_matrix(Func function) {
for (std::size_t row = 0; row < rows; ++row) {
for (std::size_t column = 0; column < columns; ++column) {
function(row, column);
}
}
}
}
Using this works without any problem, e.g.:
/*Initialize the matrix with the numbers 0..N for type T*/
template <class T>
void Matrix<T>::init_dummy_matrix(){
iterate_over_matrix(
[this](std::size_t& row, std::size_t& col) {
set_element<T>(
row, col,
col + columns * row // Same result as having a counter -> 0..N
);
}
);
}
Problem
I want to reuse this functionality on instances of the matrix-class. E.g. while calculating the outer_product in a class LinearAlgebra:
/*Set the element at position [row] and [col]umn with given [val]ue.*/
template <class T>
void Matrix<T>::set_element(const int &row, const int &col, T val) {
matrix[col + columns * row] = val;
}
/** Calculate the outer product [vector_1]T * [vector_2]. */
template <class T>
Matrix<T> LinAlg::outer_product(
const std::vector<T> &vector_1
, const std::vector<T> &vector_2
) {
Matrix matrix = Matrix<T>(
vector_1.size()
, vector_2.size()
);
matrix.iterate_over_matrix(
[this, &vector_1, &vector_2](std::size_t& row, std::size_t& col) {
set_element<T>(
row, col,
vector_1[row] * vector_2[col]
);
}
);
return matrix;
}
Anyhow, this fails with 'set_element': identifier not found.
Question
While the error-message is pretty clear in stating the problem, I have no clue how to come around this - Especially since passing the context via this does not help...
How can I access a class-function inside a lambda which is called on an instance of that object?
I have this struct:
struct abc {
int x, y;
char s[20];
};
bool comp(abc a, abc b) {
int n = strlen(a.s), m = strlen(b.s);
for(int i = 0; i < min(n,m); i++)
if(a.s[i] != b.s[i])
return a.s[i] < b.s[i];
return n < m;
}
I want to make a set with this structs sorted by s[] , but I don't know how.
One option is to overload operator< for your structure. Any standard algorithm/container that wants to compare their sort order will use that by default.
bool operator<(abc const & a, abc const & b) {
// your code here
}
Alternatively, you can specify your comparator just for the set:
std::set<abc, bool(*)(abc,abc)> my_set(comp);
This would be a bit more convenient with a function class rather than a function:
struct comp {
bool operator()(abc const & a, abc const & b) {
// your code here
}
};
std::set<abc, comp> my_set;
You need to define the < operator for abc so that stl knows how to compare two instances of abc.
So how do you compare two members of a struct that have 3 fields? Use lexicographical order.
Here is the practical implementation of your example.
struct abc {
int x, y;
char s[20];
const bool operator < ( const abc &r ) const{
return ( x< r.x)
||(( x== r.x) && ( y< r.y))
||(( x== r.x) && ( y== r.y) && strcmp(s,r.s)<0) ;
}
};
Then the set is automatically sorted when you insert in it.
How can I overload so as to make ob2[0][0] << 112.6 work? Currently I am using insert function for this operation.
template <class X>
class A
{
void insert(int row, int col, type val)
{
...
}
};
template <class Y>
class B
{
vector<int> row;
vector<vector<pair<int, Y> > > colval;
}
int main()
{
B<float> ob1;
A<B<float> > ob2;
ob2[0][0] << 112.6;
}
Use a proxy object:
class A
{
// provide operator << for a single row/column
struct cell_proxy
{
void operator<<(float value) const
{
target->insert(row, col, value);
}
A* target;
size_t row;
size_t col;
};
// provide access to elements of a single row
struct row_proxy
{
cell_proxy operator[](size_t col)
{
cell_proxy res = {target, row, col};
return res;
}
A* target;
size_t row;
};
row_proxy operator[](size_t row)
{
row_proxy res = {this, row};
return res;
}
};
That said, you can use operator overloading, proxies and templates to you delight, but you can also make code unreadeble and undebuggable. I personally find the insert() call much more readable.
Try this:
template < class E >
class B
{
vector < std::pair < int, E > inner;
public:
E& operator[] ( int i )
{
// resize inner if i is beyond current size
return ( inner [ i ].second );
}
};
template < E >
class A
{
vector < B < E > > outer;
public:
B < E >& operator[] ( int i )
{
// resize outer if i beyond current size
return ( outer [ i ] );
}
};
int main()
{
A < int > a;
a [ 2 ] [ 3 ] = 1;
return ( 0 );
}
It's a little rough around the edges, but...
I'm writing a matrix 3x3 class in c++.
glm::mat3 provides access to matrix data through the [][] operator syntax.
e.g. myMatrix[0][0] = 1.0f; would set the first row, first column entry to 1.0f.
I'd like to provide similar access. How can I overload the [][] operators?
I've tried the following, but I get errors:
operator name must be declared as a function
const real operator[][](int row, int col) const
{
// should really throw an exception for out of bounds indices
return ((row >= 0 && row <= 2) && (col >= 0 && col <= 2)) ? _data[row][col] : 0.0f;
}
What's the correct way to overload this operator?
There is no operator [][], so you need to overload the [] operator twice: once on the matrix, returning a surrogate object for the row, and once for the returned surrogate row:
// Matrix's operator[]
const row_proxy operator[](int row) const
{
return row_proxy(this, row);
}
// Proxy's operator[]
const real operator[](int col) const
{
// Proxy stores a pointer to matrix and the row passed into the first [] operator
return ((this->row >= 0 && this->row <= 2) && (col >= 0 && col <= 2)) ? this->matrix->_data[this->row][col] : 0.0f;
}
It would be easier to make the method double operator() (int row, int col) const. Instead of matrix[i][j] you just say matrix(i,j).
Generally, for multiple argument you want to use operator(), not operator[].
Hm, in case it wasn't obvious, there is no operator[][] in C++. It's just operator[] applied twice. Which means that if you want that notation, then you have to let the first one return a result (indexable thing or proxy) that the second can be applied to.
The code below sketches some approaches, choose what you like:
#include <iostream>
#include <vector>
template< int n >
int& dummy() { static int elem = n; return elem; }
struct Mat1
{
int operator() ( int const x, int const y ) const
{ return dummy<1>(); }
int& operator() ( int const x, int const y )
{ return dummy<1>(); }
Mat1( int, int ) {}
};
struct Mat2
{
int at( int const x, int const y ) const
{ return dummy<2>(); }
int& at( int const x, int const y )
{ return dummy<2>(); }
Mat2( int, int ) {}
};
struct Mat3
{
struct At { At( int x, int y ) {} };
int operator[]( At const i ) const
{ return dummy<3>(); }
int& operator[]( At const i )
{ return dummy<3>(); }
Mat3( int, int ) {}
};
class Mat4
{
protected:
int get( int const x, int const y ) const
{ return dummy<4>(); }
void set( int const x, int const y, int const v ) {}
class AssignmentProxy
{
private:
Mat4* pMat_;
int x_;
int y_;
public:
void operator=( int const v ) const
{ pMat_->set( x_, y_, v ); }
int value() const { return pMat_->get( x_, y_ ); }
operator int () const { return value(); }
AssignmentProxy( Mat4& mat, int const x, int const y )
: pMat_( &mat ), x_( x ), y_( y )
{}
};
public:
int operator()( int const x, int const y ) const
{ return get( x, y ); }
AssignmentProxy operator()( int const x, int const y )
{ return AssignmentProxy( *this, x, y ); }
Mat4( int, int ) {}
};
class Mat5
{
protected:
int at( int const x, int const y ) const
{ return dummy<4>(); }
int& at( int const x, int const y )
{ return dummy<5>(); }
class RowReadAccess
{
private:
Mat5 const* pMat_;
int y_;
public:
int operator[]( int const x ) const
{
return pMat_->at( x, y_ );
}
RowReadAccess( Mat5 const& m, int const y )
: pMat_( &m ), y_( y )
{}
};
class RowRWAccess
{
private:
Mat5* pMat_;
int y_;
public:
int operator[]( int const x ) const
{
return pMat_->at( x, y_ );
}
int& operator[]( int const x )
{
return pMat_->at( x, y_ );
}
RowRWAccess( Mat5& m, int const y )
: pMat_( &m ), y_( y )
{}
};
public:
RowReadAccess operator[]( int const y ) const
{ return RowReadAccess( *this, y ); }
RowRWAccess operator[]( int const y )
{ return RowRWAccess( *this, y ); }
Mat5( int, int ) {}
};
struct Mat6
{
private:
std::vector<int> elems_;
int width_;
int height_;
int indexFor( int const x, int const y ) const
{
return y*width_ + x;
}
public:
int const* operator[]( int const y ) const
{
return &elems_[indexFor( 0, y )];
}
int* operator[]( int const y )
{
return &elems_[indexFor( 0, y )];
}
Mat6( int const w, int const h )
: elems_( w*h, 6 ), width_( w ), height_( h )
{}
};
int main()
{
using namespace std;
enum{ w = 1024, h = 1024 };
typedef Mat3::At At;
Mat1 m1( w, h );
Mat2 m2( w, h );
Mat3 m3( w, h );
Mat4 m4( w, h );
Mat5 m5( w, h );
Mat6 m6( w, h );
wcout
<< m1( 100, 200 ) // No fuss simple, but exposes element ref.
<< m2.at( 100, 200 ) // For those who don't like operators.
<< m3[At( 100, 200)] // If you really want square brackets mnemonic.
<< m4( 100, 200 ) // Hides element ref by using assignment proxy.
<< m5[200][100] // Ditto but with square brackets (more complex).
<< m6[200][100] // The minimum fuss square brackets, exposes elem ref.
<< endl;
}
Oh well I discovered after posting that code that I haven't fully hidden the internal storage for Mat5: it needs an extra proxy level, as in Mat4. So that approach is really complex. I wouldn't do it (Mat1 is nice and easy I think), but some folks think proxys are cool, and data hiding even more cool…
Summing up, there is no “the” correct way to overload operator[]. There are many ways (as illustrated by the code above), each with some trade-offs. And generally you’re better off using operator(), because as opposed to operator[] it can take any number of arguments.
There is no [][] operator. The way GLM does it is by returning a vec3& from the first []. vec3 has its own [] operator overload. So it's two separate operator[]s on two separate classes.
This is also how GLSL works. The first [] gets the column as a vector. The second takes the vector and gets the value from it.
The expression foo[1][2] is really interpreted as (foo[1])[2], i.e. the [] operator is applied twice in succession starting with the variable foo. There is no [][] operator to be overloaded.
I would like to know if it is possible to create an actual functor object from a lambda expression. I don't think so, but if not, why?
To illustrate, given the code below, which sorts points using various policies for x and y coordinates:
#include <vector>
#include <functional>
#include <algorithm>
#include <iostream>
struct Point
{
Point(int x, int y) : x(x), y(y) {}
int x, y;
};
template <class XOrder, class YOrder>
struct SortXY :
std::binary_function<const Point&, const Point&, bool>
{
bool operator()(const Point& lhs, const Point& rhs) const
{
if (XOrder()(lhs.x, rhs.x))
return true;
else if (XOrder()(rhs.x, lhs.x))
return false;
else
return YOrder()(lhs.y, rhs.y);
}
};
struct Ascending { bool operator()(int l, int r) const { return l<r; } };
struct Descending { bool operator()(int l, int r) const { return l>r; } };
int main()
{
// fill vector with data
std::vector<Point> pts;
pts.push_back(Point(10, 20));
pts.push_back(Point(20, 5));
pts.push_back(Point( 5, 0));
pts.push_back(Point(10, 30));
// sort array
std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>());
// dump content
std::for_each(pts.begin(), pts.end(),
[](const Point& p)
{
std::cout << p.x << "," << p.y << "\n";
});
}
The expression std::sort(pts.begin(), pts.end(), SortXY<Descending, Ascending>()); sorts according to descending x values, and then to ascending y values. It's easily understandable, and I'm not sure I really want to make use of lambda expressions here.
But if I wanted to replace Ascending / Descending by lambda expressions, how would you do it? The following isn't valid:
std::sort(pts.begin(), pts.end(), SortXY<
[](int l, int r) { return l>r; },
[](int l, int r) { return l<r; }
>());
This problem arises because SortXY only takes types, whereas lambdas are objects. You need to re-write it so that it takes objects, not just types. This is basic use of functional objects- see how std::for_each doesn't take a type, it takes an object.
I have posted a similar question w.r.t. lambda functors within classes.
Check this out, perhaps it helps:
Lambda expression as member functors in a class
I had a similar problem: It was required to provide in some cases a "raw"-function pointer and in other a functor. So I came up with a "workaround" like this:
template<class T>
class Selector
{
public:
Selector(int (*theSelector)(T& l, T& r))
: selector(theSelector) {}
virtual int operator()(T& l, T& r) {
return selector(l, r);
}
int (*getRawSelector() const)(T&, T&) {
return this->selector;
}
private:
int(*selector)(T& l, T& r);
};
Assuming you have two very simple functions taking --- as described --- either a functor or a raw function pointer like this:
int
findMinWithFunctor(int* array, int size, Selector<int> selector)
{
if (array && size > 0) {
int min = array[0];
for (int i = 0; i < size; i++) {
if (selector(array[i], min) < 0) {
min = array[i];
}
}
return min;
}
return -1;
}
int
findMinWithFunctionPointer(int* array, int size, int(*selector)(int&, int&))
{
if (array && size > 0) {
int min = array[0];
for (int i = 0; i < size; i++) {
if (selector(array[i], min) < 0) {
min = array[i];
}
}
return min;
}
return -1;
}
Then you would call this functions like this:
int numbers[3] = { 4, 2, 99 };
cout << "The min with functor is:" << findMinWithFunctor(numbers, 3, Selector<int>([](int& l, int& r) -> int {return (l > r ? 1 : (r > l ? -1 : 0)); })) << endl;
// or with the plain version
cout << "The min with raw fn-pointer is:" << findMinWithFunctionPointer(numbers, 3, Selector<int>([](int& l, int& r) -> int {return (l > r ? 1 : (r > l ? -1 : 0)); }).getRawSelector()) << endl;
Of course in this example there is no real benefit passing the int's as reference...it's just an example :-)
Improvements:
You can also modify the Selector class to be more concise like this:
template<class T>
class Selector
{
public:
typedef int(*selector_fn)(T& l, T& r);
Selector(selector_fn theSelector)
: selector(theSelector) {}
virtual int operator()(T& l, T& r) {
return selector(l, r);
}
selector_fn getRawSelector() {
return this->selector;
}
private:
selector_fn selector;
};
Here we are taking advantage of a simple typedef in order to define the function pointer once and use only it's name rather then writing the declaration over and over.