Related
I have been working on a matrix library project similar to the vector library and am currently stuck at iterators. I have been trying to implement a column iterator for quite some time without the use of other libraries (besides iostream and fstream) and my workaround was to have a **columnVector that contains the references of a specified column when colBegin(i) or colEnd(i) is called. The implementation works but I can't manage to make it work aesthetically without going in myMatrix.columnVector as I want it to be encapsulated, rather I want to call matrix::iterator it = myMatrix.colBegin(i) and to iterate with addition and subtraction but my iterator subclass has only a 1d pointer (for the row iterator, hope I can use it for the column iterator as well).
Do you have an idea how to make a column iterator for a dynamically allocated 2d array?
Example of code (trying to keep it as short as possible):
using ll = unsigned long long;
template <typename Type> class matrix
{
// Iterator
public:
class iterator
{
protected:
Type* pointer;
public:
iterator() : pointer(nullptr) {}
iterator(Type* ptr);
Type& operator * ();
...
};
private:
ll numberOfColumns, numberOfRows;
Type** data;
public: // temporary, wish for it to be private
Type** columnVector;
public:
matrix() : numberOfColumns(NULL), numberOfRows(NULL), data(nullptr), columnVector(nullptr) {}
matrix(const ll, const ll);
~matrix();
Type*& operator [] (const ll value);
Type** colBegin(const ll index);
Type** colEnd(const ll index);
...
};
// Thought the constructor might be important since it allocates memory for columnVector as well
template <typename Type> matrix<Type> ::matrix(const ll _numberOfColumns, const ll _numberOfRows)
{
// Copy _numberOfColumns and _numberOfRows into this
numberOfColumns = _numberOfColumns;
numberOfRows = _numberOfRows;
// Allocates memory for data matrix
other.data = (Type**) new Type * [numberOfColumns];
for (size_t i = 0; i < numberOfColumns; i++)
other.data[i] = (Type*) new Type[numberOfRows];
// Fills data matrix with 0
for (size_t i = 0; i < other.numberOfColumns; i++)
for (size_t j = 0; j < other.numberOfRows; j++)
other.data[i][j] = 0;
// Allocation of space for columnVector
columnVector = new Type * [numberOfRows];
}
template <typename Type> Type** matrix<Type> ::colBegin(const ll index)
{
for (size_t i = 0; i < numberOfRows; i++)
columnVector[i] = &data[i][index];
return columnVector;
}
template <typename Type> Type** matrix<Type> ::colEnd(const ll index)
{
for (size_t i = 0; i < numberOfRows; i++)
columnVector[i] = &data[i][index];
return (columnVector + numberOfRows);
}
You don't even need an iterator. Each column is represented with an array. To iterate this array you need to know its beginning and the address of the element after the last one. So the Type* can represent you the iterator:
template <typename Type> class matrix
{
public:
using column_iterator = Type*;
};
So the colBegin/colEnd methods should look like that:
template<typename Type>
matrix<Type>::column_iterator matrix<Type>::colBegin(const ll index) {
return data[index];
}
template<typename Type>
matrix<Type>::column_iterator matrix<Type>::colEnd(const ll index) {
return data[index] + numberOfRows;
}
If you find that the code above iterates throught the row (which is not the case, as your contructor clearly describes data[i] as a column), you may define a class that represents an iterator:
class row_iterator {
public:
row_iterator(Type** data,
size_t rowIndex,
size_t columnIndex)
: m_data(data), m_rowIndex(rowIndex), m_columnIndex(columnIndex) {
}
bool operator == (const row_iterator &other) const {
return other.data == m_data &&
other.m_rowIndex == m_rowIndex &&
other.m_columnIndex == m_columnIndex;
}
row_iterator& operator ++() {
++m_columnIndex;
return *this;
}
row_iterator& operator ++(int) {
row_iterator temp = *this;
++*this;
return temp;
}
Type& operator *() const {
return m_data[m_columnIndex][m_rowIndex];
}
// other operators
private:
Type** m_data;
size_t m_rowIndex;
size_t m_columnIndex;
};
To use this iterator with the container you need to define:
row_iterator rowBegin(size_t rowIndex) {
return row_iterator(data, rowIndex, 0);
}
row_iterator rowEnd(size_t rowIndex) {
return row_iterator(rowIndex, rowIndex, numberOfColumns);
}
Is it possible to overload [] operator twice? To allow, something like this: function[3][3](like in a two dimensional array).
If it is possible, I would like to see some example code.
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.
For a two dimensional array, specifically, you might get away with a single operator[] overload that returns a pointer to the first element of each row.
Then you can use the built-in indexing operator to access each element within the row.
An expression x[y][z] requires that x[y] evaluates to an object d that supports d[z].
This means that x[y] should be an object with an operator[] that evaluates to a "proxy object" that also supports an operator[].
This is the only way to chain them.
Alternatively, overload operator() to take multiple arguments, such that you might invoke myObject(x,y).
It is possible if you return some kind of proxy class in first [] call. However, there is other option: you can overload operator() that can accept any number of arguments (function(3,3)).
One approach is using std::pair<int,int>:
class Array2D
{
int** m_p2dArray;
public:
int operator[](const std::pair<int,int>& Index)
{
return m_p2dArray[Index.first][Index.second];
}
};
int main()
{
Array2D theArray;
pair<int, int> theIndex(2,3);
int nValue;
nValue = theArray[theIndex];
}
Of course, you may typedef the pair<int,int>
You can use a proxy object, something like this:
#include <iostream>
struct Object
{
struct Proxy
{
Object *mObj;
int mI;
Proxy(Object *obj, int i)
: mObj(obj), mI(i)
{
}
int operator[](int j)
{
return mI * j;
}
};
Proxy operator[](int i)
{
return Proxy(this, i);
}
};
int main()
{
Object o;
std::cout << o[2][3] << std::endl;
}
If, instead of saying a[x][y], you would like to say a[{x,y}], you can do like this:
struct Coordinate { int x, y; }
class Matrix {
int** data;
operator[](Coordinate c) {
return data[c.y][c.x];
}
}
It 'll be great if you can let me know what function, function[x] and function[x][y] are. But anyway let me consider it as an object declared somewhere like
SomeClass function;
(Because you said that it's operator overload, I think you won't be interested at array like SomeClass function[16][32];)
So function is an instance of type SomeClass. Then look up declaration of SomeClass for the return type of operator[] overload, just like
ReturnType operator[](ParamType);
Then function[x] will have the type ReturnType. Again look up ReturnType for the operator[] overload. If there is such a method, you could then use the expression function[x][y].
Note, unlike function(x, y), function[x][y] are 2 separate calls. So it's hard for compiler or runtime garantees the atomicity unless you use a lock in the context. A similar example is, libc says printf is atomic while successively calls to the overloaded operator<< in output stream are not. A statement like
std::cout << "hello" << std::endl;
might have problem in multi-thread application, but something like
printf("%s%s", "hello", "\n");
is fine.
template<class F>
struct indexer_t{
F f;
template<class I>
std::result_of_t<F const&(I)> operator[](I&&i)const{
return f(std::forward<I>(i))1;
}
};
template<class F>
indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
This lets you take a lambda, and produce an indexer (with [] support).
Suppose you have an operator() that supports passing both coordinates at onxe as two arguments. Now writing [][] support is just:
auto operator[](size_t i){
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
auto operator[](size_t i)const{
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
And done. No custom class required.
#include<iostream>
using namespace std;
class Array
{
private: int *p;
public:
int length;
Array(int size = 0): length(size)
{
p=new int(length);
}
int& operator [](const int k)
{
return p[k];
}
};
class Matrix
{
private: Array *p;
public:
int r,c;
Matrix(int i=0, int j=0):r(i), c(j)
{
p= new Array[r];
}
Array& operator [](const int& i)
{
return p[i];
}
};
/*Driver program*/
int main()
{
Matrix M1(3,3); /*for checking purpose*/
M1[2][2]=5;
}
struct test
{
using array_reference = int(&)[32][32];
array_reference operator [] (std::size_t index)
{
return m_data[index];
}
private:
int m_data[32][32][32];
};
Found my own simple solution to this.
vector< vector< T > > or T** is required only when you have rows of variable length
and way too inefficient in terms of memory usage/allocations
if you require rectangular array consider doing some math instead!
see at() method:
template<typename T > class array2d {
protected:
std::vector< T > _dataStore;
size_t _sx;
public:
array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {}
T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; }
const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; }
const T& get( size_t x, size_t y ) const { return at(x,y); }
void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; }
};
The shortest and easiest solution:
class Matrix
{
public:
float m_matrix[4][4];
// for statements like matrix[0][0] = 1;
float* operator [] (int index)
{
return m_matrix[index];
}
// for statements like matrix[0][0] = otherMatrix[0][0];
const float* operator [] (int index) const
{
return m_matrix[index];
}
};
It is possible to overload multiple [] using a specialized template handler. Just to show how it works :
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
// the number '3' is the number of [] to overload (fixed at compile time)
struct TestClass : public SubscriptHandler<TestClass,int,int,3> {
// the arguments will be packed in reverse order into a std::array of size 3
// and the last [] will forward them to callSubscript()
int callSubscript(array<int,3>& v) {
return accumulate(v.begin(),v.end(),0);
}
};
int main() {
TestClass a;
cout<<a[3][2][9]; // prints 14 (3+2+9)
return 0;
}
And now the definition of SubscriptHandler<ClassType,ArgType,RetType,N> to make the previous code work. It only shows how it can be done. This solution is optimal nor bug-free (not threadsafe for instance).
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler;
template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ {
ClassType*obj;
array<ArgType,N+1> *arr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.obj = obj;
s.arr = arr;
arr->at(Recursion)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> {
ClassType*obj;
array<ArgType,N+1> *arr;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
RetType operator[](const ArgType& arg){
arr->at(0) = arg;
return obj->callSubscript(*arr);
}
};
template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{
array<ArgType,N> arr;
ClassType*ptr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype;
protected:
SubscriptHandler() {
ptr=(ClassType*)this;
}
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.arr=&arr;
s.obj=ptr;
s.arr->at(N-1)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{
RetType operator[](const ArgType&arg) {
array<ArgType,1> arr;
arr.at(0)=arg;
return ((ClassType*)this)->callSubscript(arr);
}
};
With a std::vector<std::vector<type*>>, you can build the inside vector using custom input operator that iterate over your data and return a pointer to each data.
For example:
size_t w, h;
int* myData = retrieveData(&w, &h);
std::vector<std::vector<int*> > data;
data.reserve(w);
template<typename T>
struct myIterator : public std::iterator<std::input_iterator_tag, T*>
{
myIterator(T* data) :
_data(data)
{}
T* _data;
bool operator==(const myIterator& rhs){return rhs.data == data;}
bool operator!=(const myIterator& rhs){return rhs.data != data;}
T* operator*(){return data;}
T* operator->(){return data;}
myIterator& operator++(){data = &data[1]; return *this; }
};
for (size_t i = 0; i < w; ++i)
{
data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]),
myIterator<int>(&myData[(i + 1) * h])));
}
Live example
This solution has the advantage of providing you with a real STL container, so you can use special for loops, STL algorithms, and so on.
for (size_t i = 0; i < w; ++i)
for (size_t j = 0; j < h; ++j)
std::cout << *data[i][j] << std::endl;
However, it does create vectors of pointers, so if you're using small datastructures such as this one you can directly copy the content inside the array.
Sample code:
template<class T>
class Array2D
{
public:
Array2D(int a, int b)
{
num1 = (T**)new int [a*sizeof(int*)];
for(int i = 0; i < a; i++)
num1[i] = new int [b*sizeof(int)];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
num1[i][j] = i*j;
}
}
}
class Array1D
{
public:
Array1D(int* a):temp(a) {}
T& operator[](int a)
{
return temp[a];
}
T* temp;
};
T** num1;
Array1D operator[] (int a)
{
return Array1D(num1[a]);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array2D<int> arr(20, 30);
std::cout << arr[2][3];
getchar();
return 0;
}
Using C++11 and the Standard Library you can make a very nice two-dimensional array in a single line of code:
std::array<std::array<int, columnCount>, rowCount> myMatrix {0};
std::array<std::array<std::string, columnCount>, rowCount> myStringMatrix;
std::array<std::array<Widget, columnCount>, rowCount> myWidgetMatrix;
By deciding the inner matrix represents rows, you access the matrix with an myMatrix[y][x] syntax:
myMatrix[0][0] = 1;
myMatrix[0][3] = 2;
myMatrix[3][4] = 3;
std::cout << myMatrix[3][4]; // outputs 3
myStringMatrix[2][4] = "foo";
myWidgetMatrix[1][5].doTheStuff();
And you can use ranged-for for output:
for (const auto &row : myMatrix) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
(Deciding the inner array represents columns would allow for an foo[x][y] syntax but you'd need to use clumsier for(;;) loops to display output.)
Is it possible to overload [] operator twice? To allow, something like this: function[3][3](like in a two dimensional array).
If it is possible, I would like to see some example code.
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.
For a two dimensional array, specifically, you might get away with a single operator[] overload that returns a pointer to the first element of each row.
Then you can use the built-in indexing operator to access each element within the row.
An expression x[y][z] requires that x[y] evaluates to an object d that supports d[z].
This means that x[y] should be an object with an operator[] that evaluates to a "proxy object" that also supports an operator[].
This is the only way to chain them.
Alternatively, overload operator() to take multiple arguments, such that you might invoke myObject(x,y).
It is possible if you return some kind of proxy class in first [] call. However, there is other option: you can overload operator() that can accept any number of arguments (function(3,3)).
One approach is using std::pair<int,int>:
class Array2D
{
int** m_p2dArray;
public:
int operator[](const std::pair<int,int>& Index)
{
return m_p2dArray[Index.first][Index.second];
}
};
int main()
{
Array2D theArray;
pair<int, int> theIndex(2,3);
int nValue;
nValue = theArray[theIndex];
}
Of course, you may typedef the pair<int,int>
You can use a proxy object, something like this:
#include <iostream>
struct Object
{
struct Proxy
{
Object *mObj;
int mI;
Proxy(Object *obj, int i)
: mObj(obj), mI(i)
{
}
int operator[](int j)
{
return mI * j;
}
};
Proxy operator[](int i)
{
return Proxy(this, i);
}
};
int main()
{
Object o;
std::cout << o[2][3] << std::endl;
}
If, instead of saying a[x][y], you would like to say a[{x,y}], you can do like this:
struct Coordinate { int x, y; }
class Matrix {
int** data;
operator[](Coordinate c) {
return data[c.y][c.x];
}
}
It 'll be great if you can let me know what function, function[x] and function[x][y] are. But anyway let me consider it as an object declared somewhere like
SomeClass function;
(Because you said that it's operator overload, I think you won't be interested at array like SomeClass function[16][32];)
So function is an instance of type SomeClass. Then look up declaration of SomeClass for the return type of operator[] overload, just like
ReturnType operator[](ParamType);
Then function[x] will have the type ReturnType. Again look up ReturnType for the operator[] overload. If there is such a method, you could then use the expression function[x][y].
Note, unlike function(x, y), function[x][y] are 2 separate calls. So it's hard for compiler or runtime garantees the atomicity unless you use a lock in the context. A similar example is, libc says printf is atomic while successively calls to the overloaded operator<< in output stream are not. A statement like
std::cout << "hello" << std::endl;
might have problem in multi-thread application, but something like
printf("%s%s", "hello", "\n");
is fine.
template<class F>
struct indexer_t{
F f;
template<class I>
std::result_of_t<F const&(I)> operator[](I&&i)const{
return f(std::forward<I>(i))1;
}
};
template<class F>
indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
This lets you take a lambda, and produce an indexer (with [] support).
Suppose you have an operator() that supports passing both coordinates at onxe as two arguments. Now writing [][] support is just:
auto operator[](size_t i){
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
auto operator[](size_t i)const{
return as_indexer(
[i,this](size_t j)->decltype(auto)
{return (*this)(i,j);}
);
}
And done. No custom class required.
#include<iostream>
using namespace std;
class Array
{
private: int *p;
public:
int length;
Array(int size = 0): length(size)
{
p=new int(length);
}
int& operator [](const int k)
{
return p[k];
}
};
class Matrix
{
private: Array *p;
public:
int r,c;
Matrix(int i=0, int j=0):r(i), c(j)
{
p= new Array[r];
}
Array& operator [](const int& i)
{
return p[i];
}
};
/*Driver program*/
int main()
{
Matrix M1(3,3); /*for checking purpose*/
M1[2][2]=5;
}
struct test
{
using array_reference = int(&)[32][32];
array_reference operator [] (std::size_t index)
{
return m_data[index];
}
private:
int m_data[32][32][32];
};
Found my own simple solution to this.
vector< vector< T > > or T** is required only when you have rows of variable length
and way too inefficient in terms of memory usage/allocations
if you require rectangular array consider doing some math instead!
see at() method:
template<typename T > class array2d {
protected:
std::vector< T > _dataStore;
size_t _sx;
public:
array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {}
T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; }
const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; }
const T& get( size_t x, size_t y ) const { return at(x,y); }
void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; }
};
The shortest and easiest solution:
class Matrix
{
public:
float m_matrix[4][4];
// for statements like matrix[0][0] = 1;
float* operator [] (int index)
{
return m_matrix[index];
}
// for statements like matrix[0][0] = otherMatrix[0][0];
const float* operator [] (int index) const
{
return m_matrix[index];
}
};
It is possible to overload multiple [] using a specialized template handler. Just to show how it works :
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
// the number '3' is the number of [] to overload (fixed at compile time)
struct TestClass : public SubscriptHandler<TestClass,int,int,3> {
// the arguments will be packed in reverse order into a std::array of size 3
// and the last [] will forward them to callSubscript()
int callSubscript(array<int,3>& v) {
return accumulate(v.begin(),v.end(),0);
}
};
int main() {
TestClass a;
cout<<a[3][2][9]; // prints 14 (3+2+9)
return 0;
}
And now the definition of SubscriptHandler<ClassType,ArgType,RetType,N> to make the previous code work. It only shows how it can be done. This solution is optimal nor bug-free (not threadsafe for instance).
#include <iostream>
#include <algorithm>
#include <numeric>
#include <tuple>
#include <array>
using namespace std;
template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler;
template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ {
ClassType*obj;
array<ArgType,N+1> *arr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.obj = obj;
s.arr = arr;
arr->at(Recursion)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> {
ClassType*obj;
array<ArgType,N+1> *arr;
friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>;
friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
public:
RetType operator[](const ArgType& arg){
arr->at(0) = arg;
return obj->callSubscript(*arr);
}
};
template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{
array<ArgType,N> arr;
ClassType*ptr;
typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype;
protected:
SubscriptHandler() {
ptr=(ClassType*)this;
}
public:
Subtype operator[](const ArgType& arg){
Subtype s;
s.arr=&arr;
s.obj=ptr;
s.arr->at(N-1)=arg;
return s;
}
};
template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{
RetType operator[](const ArgType&arg) {
array<ArgType,1> arr;
arr.at(0)=arg;
return ((ClassType*)this)->callSubscript(arr);
}
};
With a std::vector<std::vector<type*>>, you can build the inside vector using custom input operator that iterate over your data and return a pointer to each data.
For example:
size_t w, h;
int* myData = retrieveData(&w, &h);
std::vector<std::vector<int*> > data;
data.reserve(w);
template<typename T>
struct myIterator : public std::iterator<std::input_iterator_tag, T*>
{
myIterator(T* data) :
_data(data)
{}
T* _data;
bool operator==(const myIterator& rhs){return rhs.data == data;}
bool operator!=(const myIterator& rhs){return rhs.data != data;}
T* operator*(){return data;}
T* operator->(){return data;}
myIterator& operator++(){data = &data[1]; return *this; }
};
for (size_t i = 0; i < w; ++i)
{
data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]),
myIterator<int>(&myData[(i + 1) * h])));
}
Live example
This solution has the advantage of providing you with a real STL container, so you can use special for loops, STL algorithms, and so on.
for (size_t i = 0; i < w; ++i)
for (size_t j = 0; j < h; ++j)
std::cout << *data[i][j] << std::endl;
However, it does create vectors of pointers, so if you're using small datastructures such as this one you can directly copy the content inside the array.
Sample code:
template<class T>
class Array2D
{
public:
Array2D(int a, int b)
{
num1 = (T**)new int [a*sizeof(int*)];
for(int i = 0; i < a; i++)
num1[i] = new int [b*sizeof(int)];
for (int i = 0; i < a; i++) {
for (int j = 0; j < b; j++) {
num1[i][j] = i*j;
}
}
}
class Array1D
{
public:
Array1D(int* a):temp(a) {}
T& operator[](int a)
{
return temp[a];
}
T* temp;
};
T** num1;
Array1D operator[] (int a)
{
return Array1D(num1[a]);
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Array2D<int> arr(20, 30);
std::cout << arr[2][3];
getchar();
return 0;
}
Using C++11 and the Standard Library you can make a very nice two-dimensional array in a single line of code:
std::array<std::array<int, columnCount>, rowCount> myMatrix {0};
std::array<std::array<std::string, columnCount>, rowCount> myStringMatrix;
std::array<std::array<Widget, columnCount>, rowCount> myWidgetMatrix;
By deciding the inner matrix represents rows, you access the matrix with an myMatrix[y][x] syntax:
myMatrix[0][0] = 1;
myMatrix[0][3] = 2;
myMatrix[3][4] = 3;
std::cout << myMatrix[3][4]; // outputs 3
myStringMatrix[2][4] = "foo";
myWidgetMatrix[1][5].doTheStuff();
And you can use ranged-for for output:
for (const auto &row : myMatrix) {
for (const auto &elem : row) {
std::cout << elem << " ";
}
std::cout << std::endl;
}
(Deciding the inner array represents columns would allow for an foo[x][y] syntax but you'd need to use clumsier for(;;) loops to display output.)
I recently stumbled across expression templates in C++. There is one thing that I do not quite understand about their implementation, and that is why the base class is necessary (from which all other objects relating to template expression derive in a CRTP manner). A simple example that does addition and scalar multiplication on vectors (objects of type Vec, without base class):
#include <vector>
#include <iostream>
using namespace std;
class Vec
{
vector<double> data;
public:
template<typename E>
Vec(E expr)
{
data = vector<double>(expr.size());
for (int i = 0; i < expr.size(); i++)
data[i] = expr[i];
}
Vec(int size)
{
data = vector<double>(size);
for (int i = 0; i < size; i++)
data[i] = i;
}
double operator [] (int idx) {
return data[idx];
}
int size() { return data.size(); }
bool operator < (Vec &rhs)
{
return (*this)[0] < rhs[0];
}
bool operator > (Vec &rhs)
{
return (*this)[0] > rhs[0];
}
};
template<typename E1, typename E2>
class VecAdd
{
E1 vec_expr1;
E2 vec_expr2;
public:
VecAdd(E1 vec_expr1, E2 vec_expr2) : vec_expr1(vec_expr1), vec_expr2(vec_expr2)
{}
double operator [] (int idx) { return vec_expr1[idx] + vec_expr2[idx]; }
int size() { return vec_expr1.size(); }
};
template<typename E>
class ScalarMult
{
E vec_expr;
double scalar;
public:
ScalarMult(double scalar, E vec_expr) : scalar(scalar), vec_expr(vec_expr)
{}
double operator [] (int idx) { return scalar*vec_expr[idx]; }
int size() { return vec_expr.size(); }
};
template<typename E1, typename E2>
VecAdd<E1, E2> operator + (E1 vec_expr1, E2 vec_expr2)
{
return VecAdd<E1, E2>(vec_expr1, vec_expr2);
}
template<typename E>
ScalarMult<E> operator * (double scalar, E vec_expr)
{
return ScalarMult<E>(scalar, vec_expr);
}
int main()
{
Vec term1(5);
Vec term2(5);
Vec result = 6*(term1 + term2);
Vec result2 = 4 * (term1 + term2 + term1);
//vector<Vec> vec_vector = {result, result2}; does not compile
vector<Vec> vec_vector;
vec_vector = { result2, result }; //compiles
vec_vector.clear();
vec_vector.push_back(result);
vec_vector.push_back(result2); //all this compiles
for (int i = 0; i < result.size(); i++)
cout << result[i] << " ";
cout << endl;
system("pause");
return 0;
}
The code above compiles (except for the indicated line), and it evaluates the simple expressions in the main function without fault. If the expressions get assigned to an object of type Vec and assign their contents to a Vec object, getting destroyed in the process in any case, why is it necessary for a base class? (as shown in this Wikipedia article)
EDIT:
I know this code is a bit messy and bad (copying where unnecessary, etc.) but I am not planning on using this specific code. This is just to illustrate that expression templates work in this example without the CRTP base class - and I am trying to figure out exactly why this base class is necessary.
Your
template<typename E1, typename E2>
VecAdd<E1, E2> operator + (E1 vec_expr1, E2 vec_expr2)
will match for any user-defined types, not merely expression types. When instantiated with non-vector types, it will then likely fail. This interacts very badly with other C++ types, quite possibly including standard library types, which provide their own custom operator + and may rely on inexact matches resolving to their own operator + after implicit conversions.
Making operator + only available for VecExpression<E> avoids that problem.
A while ago, I found in a website some code examples of utility functions that are used when creating, destructing objects, or even when overloading some of their operators.
More precisely, the following member functions are mainly used: init, copy, set, and destroy.
The init member function is used to initialize all the private members. It's mostly called inside the constructors, e.g. the default or parameter constructor.
The copy member function is used to do a deep copy of an object passed as a const reference. It is called inside the reference constructor and the overload of the operator =.
The set member function which mainly allocates memory for the private members that require it.
Finally, the destroy member function is used for releasing the allocated memory. It's called, for example, inside of the destructor.
I would like to have your opinion and know if this is a good programming practice? Which are the benefits or drawbacks? Any comments and suggestions are welcomed!
Below, I'm illustrating how those member functions are defined for a CMatrix<T> class.
matrix.h
template < class T >
class CMatrix{
CMatrix(){ this->initMatrix(); }
CMatrix(int nRows, int nCols, int nChannels){
this->initComplexMatrix();
this->setComplexMatrix(nRows, nCols, nChannels);
}
CMatrix(const CMatrix<T> & refMatrix){
this->initComplexMatrix();
this->copyComplexMatrix(refMatrix);
}
CMatrix<T> & operator = (const CMatrix<T> & refMatrix){
if(this!=&refMatrix){
this->destroyComplexMatrix();
this->initComplexMatrix();
this->copyComplexMatrix(refMatrix);
}
return (*this);
}
T & CMatrix<T>::operator()(int, int, int);
T CMatrix<T>::operator()(int, int, int) const;
......
void initMatrix();
void copyMatrix(const CMatrix<T> & );
void setMatrix(int, int, int = 1);
void destroyMatrix();
......
~CMatrix(){ this->destroyMatrix(); }
private:
T *** m_pData;
int m_nRows;
int m_nCols;
int m_nChannels;
};
matrix.cpp
#include <matrix.h>
template < class T >
inline T & CMatrix<T>::operator()(int mrow, int mcol, int mchannel){
assert(mrow >= 0 && mrow < this->getRows());
assert(mcol >= 0 && mcol < this->getCols());
assert(mchannel >= 0 && mchannel < this->getChannels());
return this->m_pData[mrow][mcol][mchannel];
}
template < class T >
void CMatrix<T>::initMatrix(){
this->m_nRows = 0;
this->m_nCols = 0;
this->m_nChannels= 0;
this->m_pData = NULL;
}
template < class T >
void CMatrix<T>::copyMatrix(const CMatrix<T> & refMatrix){
if(refMatrix.m_pData!=NULL){
this->setMatrix(refMatrix.getRows(), refMatrix.getCols(), refMatrix.getChannels());
for(register int dy=0; dy < this->getRows(); dy++){
for(register int dx=0; dx < this->getCols(); dx++){
for(register int ch=0; ch < this->getChannels(); ch++){
this->m_pData[(dy)][(dx)][(ch)] = refMatrix.m_pData[(dy)][(dx)][(ch)];
}
}
}
}
else{
this->m_pData = NULL;
}
}
template < class T >
void CMatrix<T>::setMatrix(int nRows, int nCols, int nChannels){
this->destroyMatrix();
this->m_pData = NULL;
this->m_pData = new T ** [nRows];
for(register int dy=0; dy < nRows; dy++){
this->m_pData[dy] = NULL;
this->m_pData[dy] = new T * [nCols];
for(register int dx=0; dx < nCols; dx++){
this->m_pData[dy][dx] = NULL;
this->m_pData[dy][dx] = new T[nChannels];
}
}
this->setRows(mrows);
this->setCols(mcols);
this->setChannels(mchannels);
}
template < class T >
void CMatrix<T>::destroyMatrix(){
if(this->m_pData!=NULL){
for(register int dy=0; dy < this->getRows(); dy++){
for(register int dx=0; dx < this->getCols(); dx++){
delete [] this->m_pData[dy][dx];
}
delete [] this->m_pData[dy];
}
delete [] this->m_pData;
this->m_pData = NULL;
}
}
No, this is not recommended. The way you propose is not exception safe and is not compatible with const or subobjects that need non-default construction.
Instead use the ctor-initializer-list. Code reuse can be achieved through static helper functions called in the ctor-initializer-list or by moving logic into subobject constructors.
For memory allocation, use a subobject per resource. The memory management logic ends up in the subobject constructor and destructor. In many cases, you can use existing RAII classes from the library, such as std::vector, and not need to write any memory management code yourself.
Most operators can reuse the logic in the constructors, using the copy-and-swap idiom.
EDIT: Exception-safe construction might look something like this:
#include <vector>
template<typename T>
class matrix
{
int m_nCols;
std::vector<T*> m_rows;
std::vector<T> m_cells;
size_t makeIndex( int row, int col ) const { return row*m_nCols + col; }
public:
matrix( int nRows, int nCols )
: m_nCols(nCols), m_rows(nRows), m_cells(nRows * nCols)
{
while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
}
matrix( const matrix<T>& other )
: m_nCols(other.m_nCols), m_rows(other.m_rows.size()), m_cells(other.m_cells)
{
int nRows = other.m_rows.size();
while (nRows--) m_rows[nRows] = &m_cells[nRows * nCols];
}
void swap( matrix& other )
{
using std::swap;
swap(m_nCols, other.m_nCols);
swap(m_rows, other.m_rows);
swap(m_cells, other.m_cells);
}
matrix& operator=( matrix other )
{
other.swap(*this);
return *this;
}
const T& operator()( int row, int col ) const { return m_cells[makeIndex(row,col)]; }
T& operator()( int row, int col ) { return m_cells[makeIndex(row,col)]; }
};
The std::vector destructor will take care of freeing the memory, and since the two allocations are separate objects, if m_cells fails to allocate its memory, the destructor for m_rows will run and nothing will leak.
Of course, std::vector is a little bit overkill here, a fixed-size array RAII class would be sufficient. But std::auto_ptr can't be used with arrays. I think C++0x is supposed to add a standard fixed-size RAII array class.
EDIT: Per request, a 3-D version:
#include <vector>
template<typename T>
class cube
{
int m_nCols, m_nRows;
std::vector<T> m_cells;
size_t makeIndex( int row, int col, int channel ) const { return (channel*m_nRows + row)*m_nCols + col; }
public:
cube( int nRows, int nCols, int nChannels )
: m_nCols(nCols), m_nRows(nRows), m_cells(nRows * nCols * nChannels)
{
}
cube( const cube<T>& other )
: m_nCols(other.m_nCols), m_nRows(other.m_nRows), m_cells(other.m_cells)
{
}
void swap( cube& other )
{
using std::swap;
swap(m_nCols, other.m_nCols);
swap(m_nRows, other.m_nRows);
swap(m_cells, other.m_cells);
}
cube& operator=( cube other )
{
other.swap(*this);
return *this;
}
const T& operator()( int row, int col, int channel ) const { return m_cells[makeIndex(row,col,channel)]; }
T& operator()( int row, int col, int channel ) { return m_cells[makeIndex(row,col,channel)]; }
class channel_iterator
{
cube& const cube;
int const row, col;
int channel;
friend class cube;
channel_iterator( cube& all, int r, int c, int n ) : cube(all), row(r), col(c), channel(n) {}
public:
T& operator*() const { return cube(row, col, channel); }
channel_iterator& operator++() { ++channel; return *this; }
channel_iterator operator++(int) { return channel_iterator(cube, row, col, channel++); }
bool operator!=(const channel_iterator& other) const { assert(&cube == &other.cube); return (row == other.row && col == other.col && channel == other.channel); }
};
int channel_count() const { return m_cells.size() / m_nRows / m_nChannels; }
pair<channel_iterator, channel_iterator> range(int row, int col) { return make_pair(channel_iterator(*this, row, col, 0), channel_iterator(*this, row, col, channel_count())); }
};
A better pattern for implementing assignment is the copy and swap idiom.
X& X::operator= (const X& rhv)
{
X copy(rhv); //reuse copy constructor
this->swap(copy); //reuse swap method - also useful for the user of the class!
//previously held resources automatically released by the destructor of copy
}
This performs the necessary steps in an order that keeps left-hand value unchanged if an exception occurs during the copying: doesn't release resources before new resources have been successfully obtained.
And the advantage over the methods you have is that the swap method is useful not only internally for implementing the class, but also for the user of the class. In case of the CMatrix class the implementation would be:
void CMatrix<T>::swap(CMatrix<T>& other)
{
std::swap(m_pData, other.m_pData);
std::swap(m_nRows, other.m_nRows);
std::swap(m_nCols, other.m_nCols);
std::swap(m_nChannels, other.m_nChannels);
}
Also, if suitable, it is a better idea to reuse existing RAII classes instead of managing memory manually in each and every class.