I store 3D data in a std::vector-based structure:
std::shared_ptr< std::vector< std::vector< std::vector< Type > > > > data;
I allocate this structure by calling resize while iterating through the vectors:
arraydata.reset(new std::vector< std::vector< std::vector< Type > > >());
arraydata->resize(m_width);
for (unsigned int col_index = 0; col_index < m_width; ++col_index)
{
(*arraydata)[col_index].resize(m_height);
for (unsigned int line_index = 0; line_index < m_height; ++line_index)
{
(*arraydata)[col_index][line_index].resize(m_nbbands);
}
}
But this allocation takes a lot of time when the dimensions are big...
Is there a way to allocate in a single operation all the needed space (with malloc(m_width*m_height*m_nbbands*sizeof(Type)) for example) and then to assign to each vector its own data space in the global space ? Would it be more performant ?
Edit: I tested #justin-time's idea
arraydata.reset(new std::vector< std::vector< std::vector< T > > >(m_width,
std::vector< std::vector< T > >(m_height, std::vector< T > (m_nbbands))));
gives an execution time comparable to original code, around 4.9 s for allocation and 40 s for deallocation ???
This can be seen in the memory manager:
I don't succeed in testing allocation from a malloc, this code fails at std::vector< T > tmp(datptr, (T*)(datptr+arraySize));
unsigned int arraySize = m_nbbands*sizeof(T);
T *datptr = (T*)malloc(m_width*m_height*arraySize);
arraydata.reset(new std::vector< std::vector< std::vector< T > > >(m_width));
for (unsigned int col_index = 0; col_index < m_width; ++col_index)
{
(*arraydata)[col_index].resize(m_height);
for (unsigned int line_index = 0; line_index < m_height; ++line_index)
{
std::vector< T > tmp(datptr, (T*)(datptr+arraySize));
(*arraydata)[col_index][line_index].swap(tmp);
// also tested with same results:
//(*arraydata)[col_index][line_index] =
// std::vector< T >(datptr, (T*)(datptr+arraySize));
datptr += arraySize;
}
}
Don't use a vector of vector of vectors. Use a class which has an internal array and then provides a way to access the elements. For example:
template <typename T>
class vec3d {
std::vector<T> data;
size_t xmax, ymax, zmax;
public:
T& operator()(size_t x, size_t y, size_t z)
{ return data[x+y*xmax+z*xmax*ymax]; }
const T& operator()(size_t x, size_t y, size_t z)
{ return data[x+y*xmax+z*xmax*ymax]; }
vec3d(size_t x, size_t y, size_t z)
: xmax(x), ymax(y), zmax(z), data(x*y*z) {}
T& v(size_t x, size_t y, size_t z) { return (*this)(x,y,z); }
};
access would then be like
shared_ptr<vec3d<int>> p = make_shared<vec3d<int>>(10, 20, 30);
p->v(5,6,7) = 14;
or
vec3d vec(5,6,7);
vec(1,2,4) = 16.0f; // Fortran style indexing.
You will probably want some more members to allow iteration, the dimensions, etc. Because this is a single allocation, it will be much faster.
Following Martin Bonner's answer, I came to the following solution, for which allocation and deallocation take less than a second.
Data is accessible with arraydata[x][y][z].
arraydata = std::make_shared< CImageStorage< T > >(m_width,
m_height, m_nbbands, bppixel);
with
template<class T>
class CImageStorage1D
{
T* data;
unsigned int m_nbbands;
public:
CImageStorage1D(T* p, unsigned int nbbands) :
data(p), m_nbbands(nbbands) {}
T& DataPtr(unsigned int band) { return data[band]; }
const T& DataPtr(unsigned int band) const { return data[band]; }
T& operator[](unsigned int band) { return (data[band]); }
const T& operator[] (unsigned int band) const { return (data[band]); }
unsigned int size()const { return m_nbbands; }
};
template<class T>
class CImageStorage2D
{
T* data;
unsigned int m_height, m_nbbands, m_bppixel;
public:
CImageStorage2D(T* p, unsigned int height, unsigned int nbbands,
unsigned int bppixel, std::shared_ptr< std::vector<int> > heightShift) :
data(p), m_height(height), m_nbbands(nbbands), m_bppixel(bppixel) {}
T* DataPtr(unsigned int height) { return (T*)(data+m_height*m_nbbands); }
const T* DataPtr(unsigned int height) const {
return (T*)(data+m_height*m_nbbands); }
CImageStorage1D<T> operator[](unsigned int height) {
return CImageStorage1D<T>((T*)(data+m_height*m_nbbands), m_nbbands); }
const CImageStorage1D<T> operator[] (unsigned int height) const {
return CImageStorage1D<T>((T*)(data+m_height*m_nbbands), m_nbbands); }
unsigned int size()const { return m_height; }
};
template<class T>
class CImageStorage
{
T* data;
unsigned int m_width, m_height, m_nbbands, m_bppixel;
public:
CImageStorage(unsigned int width, unsigned int height, unsigned int nbbands,
unsigned int bppixel) :
m_width(width), m_height(height), m_nbbands(nbbands), m_bppixel(bppixel)
{
data = (T*)malloc(m_width*m_height*m_nbbands*m_bppixel);
}
~CImageStorage() { free(data); }
bool IsValid() { return (data != nullptr); }
T** DataPtr(unsigned int width) {
return (T**)(data+width*m_height*m_nbbands); }
const T** DataPtr(unsigned int width) const {
return (T**)(data+width*m_height*m_nbbands); }
CImageStorage2D<T> operator[](unsigned int width) {
return CImageStorage2D<T>( (T*)(data+width*m_height*m_nbbands),
m_height, m_nbbands, m_bppixel); }
const CImageStorage2D<T> operator[] (unsigned int width) const {
return CImageStorage2D<T>((T*)(data+width*m_height*m_nbbands),
m_height, m_nbbands, m_bppixel); }
unsigned int size()const { return m_width; }
};
Related
I have created a structure that contains a vector of unsigned integers for bitstream handling. Essentially, values are written to this vector in sets that are no more than 64 bits long.
The strange behavior comes into play with different images used. Running the entire code on various images yields strange results. Some images (no correlation to size) will properly encode and write to the ofstream while others will cause a vector emplace_back error at the line "ints.emplace_back(field())".
As I am sure most reading this will suggest, I have added a .reserve line to increase the capacity. This does fix this problem, but then (for the same images) a new problem occurs when writing the vector to the file. Now an error occurs in fstream at line
_Count -= _CSTD fwrite(_Ptr, sizeof(_Elem), static_cast<size_t>(_Count), _Myfile);
But again, this error does not happen for most of the other images that are both the same dimensions or larger or smaller. Any reason for this strange behavior? Or perhaps suggestions on a way to fix the fwrite error? I tried shrink_to_fit() but that causes the same malloc error when shrinking to fit.
Here is the relevant code:
(structures)
struct field {
private:
uint32_t bits;
public:
field() : bits(0) {}
operator uint32_t() { return bits; }
inline uint32_t pack() { return bits; }
field& set_bits(uint32_t val, uint8_t pos) {
bits |= (val << pos);
return *this;
}
uint32_t get_bits(uint8_t a, uint8_t b) {
return (bits >> a) & ~(0xFFFFFFFF << (b - a));
}
};
struct bstream {
private:
std::vector<field> ints;
size_t position;
size_t length;
public:
bstream() : position(0), ints(0), length(0) {}
bstream(const bstream& p1) { position = p1.position; ints = p1.ints; length = p1.length; }
field* data() { return ints.data(); }
int get_size() { return (ceil(position / 32.0)); } // returns how many bytes there are
int max_size() { return ints.max_size(); }
int size() { return ints.size(); }
int capacity() { return ints.capacity(); }
bstream& resize(int size) { ints.resize(floor(size / 4)); length = floor(size / 4); return *this; }
bstream& reserve(int size) { ints.reserve(size); return *this; }
bstream& shrink_to_fit() { ints.shrink_to_fit(); return *this; }
bstream& push_chunk(uint32_t C, int Q) {
const int a = (position % 32);
const int b = a + Q;
if (a == 0)
ints.emplace_back(field());
if (b > 32) {
ints.back().set_bits(C, a);
position += (32 - a);
this->push_chunk(C >> (32 - a), b - 32);
}
else {
ints.back().set_bits(C, a);
position += Q;
}
return *this;
}
uint32_t pop_chunk(int Q) {}
bstream& write_int(int C, int Q, const int qmin, bool is_signed) {
this->push_chunk(abs(C) >> qmin, Q - qmin);
if (is_signed && (abs(C) >> qmin) != 0)
this->push_chunk(int(0) < C, 1);
return *this;
}
int read_int(int Q, const int qmin, bool is_signed) {}
bstream& write_descent(int A, int B, const int qmin) {}
int read_descent(int A, const int qmin) {}
bstream& encode_group(int* Q, int* C, int index, int qmin, int sizeQ, int sizeC) {}
bstream& encode_coeffs(int Qg, int Q, int* C, int index, int qmin) {}
void decode_group(int* Q, int* C, int index, int qmin, int sizeQ, int sizeC) {}
void decode_coeffs(int Qg, int& Q, int* C, int index, int qmin) {}
void print() {}
};
(Line used to write to ofstream)
outFile->write(reinterpret_cast<char*>(STREAM.data()), 4.0 * STREAM.get_size());
I'm attempting to get a basic constant forward-iterator to work in C++.
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
int begin_col(int j) { return p[j]; };
int end_col(int j) { return p[j + 1]; };
class iterator {
public:
int index;
iterator(SparseMatrix& g) : parent(g) {}
iterator(int ind) { index = ind; }; // ERROR!
bool operator!=(int x) const { return index != x; };
iterator operator++(int) { ++index; return (*this); };
int row() { return parent.i[index]; };
double value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
};
}
My intention is to use the iterator in contexts similar to the following:
// sum of values in column 7
Rcpp::SparseMatrix A(nrow, ncol, fill::random);
double sum = 0;
for(Rcpp::SparseMatrix::iterator it = A.begin_col(7); it != A.end_col(7); it++)
sum += it.value();
Two questions:
The compiler throws an error on the line indicated above: uninitialized reference member in 'class Rcpp::SparseMatrix&' [-fpermissive]. How can this be fixed?
How might double value() { return parent.x[index]; }; be re-worked to return a pointer to the value rather than a copy of the value?
A little context on the SparseMatrix class: like a dgCMatrix in R, this object of class SparseMatrix consists of three vectors:
i holds row pointers for every element in x
p gives indices in i which correspond to the start of each column
x contains non-zero values
Thanks to #Evg, here's the solution:
namespace Rcpp {
class SparseMatrix {
public:
IntegerVector i, p;
NumericVector x;
class iterator {
public:
int index;
iterator(SparseMatrix& g, int ind) : parent(g) { index = ind; }
bool operator!=(iterator x) const { return index != x.index; };
iterator& operator++() { ++index; return (*this); };
int row() { return parent.i[index]; };
double& value() { return parent.x[index]; };
private:
SparseMatrix& parent;
};
iterator begin_col(int j) { return iterator(*this, p[j]); };
iterator end_col(int j) { return iterator(*this, p[j + 1]); };
};
}
And it can be used as follows, for instance, to calculate colSums:
//[[Rcpp::export]]
Rcpp::NumericVector Rcpp_colSums(Rcpp::SparseMatrix& A) {
Rcpp::NumericVector sums(A.cols());
for (int i = 0; i < A.cols(); ++i)
for (Rcpp::SparseMatrix::iterator it = A.begin_col(i); it != A.end_col(i); it++)
sums(i) += it.value();
return sums;
}
And, the above function is faster than RcppArmadillo, RcppEigen, and R::Matrix equivalents when microbenchmarked from R!
Edit:
The above syntax is inspired by Armadillo. I've come to realize that a slightly different syntax (which involves fewer constructions) gives an iterator similar to Eigen:
class col_iterator {
public:
col_iterator(SparseMatrix& ptr, int col) : ptr(ptr) { indx = ptr.p[col]; max_index = ptr.p[col + 1]; }
operator bool() const { return (indx != max_index); }
col_iterator& operator++() { ++indx; return *this; }
const double& value() const { return ptr.x[indx]; }
int row() const { return ptr.i[indx]; }
private:
SparseMatrix& ptr;
int indx, max_index;
};
Which can then be used like this:
int col = 0;
for (Rcpp::SparseMatrix::col_iterator it(A, col); it; ++it)
Rprintf("row: %3d, value: %10.2e", it.row(), it.value());
I write a small animation program with OpenSceneGraph(osg). In each frame, I should update the models(vertex position,normal, color and other stuff) in the scene.
Now I shoudl convert the data to osg in each frame. The code is like:
cog_.vertex_->clear();
cog_.vertex_->push_back(osg::Vec3(1.0,1.0,1.0));
However these convertion is very time consuming. So I'm wondering how to access data directly via pointer. I tried but failed. The following is what I did, hope someone can help me to find the problem, or tell me better solution:
First, I wrap the a pointer to osg::Vec3,
class vec3_map : public osg::Vec3
{
public:
typedef osg::Vec3::value_type value_type;
osg::Vec3::value_type* p_;
vec3_map() :p_(0) {}
vec3_map(osg::Vec3::value_type*p, int offset = 0) :p_(p+offset){}
inline value_type& x() { return *(p_+0); }
inline value_type& y() { return *(p_+1); }
inline value_type& z() { return *(p_+2); }
// some other stuff
};
When I want to build an array of vec3_map, I found that osg use a tempalte to typedef Vec3Array, but there isn't any type for a pointer, so I choose the closet one (I know pointer is a variable with unsigned long int type):
typedef osg::TemplateArray<vec3_map, osg::Array::UIntArrayType, 1, GL_UNSIGNED_INT> Vec3_map_Array;
With this definition, I can rewrite my problem to the following:
#define BOOST_ALL_NO_LIB
#include <boost/shared_ptr.hpp>
#include <fstream>
#include <vector>
#include <osg/Group>
#include <osg/Geometry>
#include <osgViewer/Viewer>
#include <osg/Vec3>
class vec3_map : public osg::Vec3
{
public:
typedef osg::Vec3::value_type value_type;
osg::Vec3::value_type* p_;
vec3_map() :p_(0) {}
vec3_map(osg::Vec3::value_type*p, int offset = 0) :p_(p + offset) {}
inline value_type* ptr() { return p_; }
inline const value_type* ptr() const { return p_; }
inline value_type& operator [] (int i) { return *(p_ + i); }
inline value_type operator [] (int i) const { return *(p_ + i); }
inline value_type& x() { return *(p_ + 0); }
inline value_type& y() { return *(p_ + 1); }
inline value_type& z() { return *(p_ + 2); }
inline value_type x() const { return *(p_); }
inline value_type y() const { return *(p_ + 1); }
inline value_type z() const { return *(p_ + 2); }
};
typedef osg::TemplateArray<vec3_map, osg::Array::UIntArrayType, 1, GL_UNSIGNED_INT> Vec3_map_Array;
struct point_data
{
point_data(float xx, float yy, float zz) { x = xx; y = yy; z = zz; }
float x;
float y;
float z;
};
osg::Geode* create_point_node(boost::shared_ptr<std::vector<point_data> > ptr)
{
osg::Geode *geode_ = new osg::Geode;
osg::Geometry* geometry_ = new osg::Geometry;
Vec3_map_Array* vertex_ = new Vec3_map_Array;
osg::DrawElementsUInt* point_idx_ = new osg::DrawElementsUInt;
vertex_->reserve(ptr->size());
point_idx_->reserve(ptr->size());
vec3_map vm;
std::vector<point_data> & pd = *ptr;
for (size_t i = 0; i < ptr->size(); ++i)
{
vertex_->push_back(vec3_map(&(pd[i].x)));
point_idx_->push_back(i);
}
geometry_->setVertexArray(vertex_);
geometry_->addPrimitiveSet(point_idx_);
geode_->addDrawable(geometry_);
return geode_;
}
int main(int argc, char *argv[])
{
boost::shared_ptr<std::vector<point_data> > pd(new std::vector<point_data>);
pd->push_back(point_data(1.0, 1.0, 1.0));
pd->push_back(point_data(2.0, 2.0, 2.0));
osgViewer::Viewer viewer;
osg::Node *node = create_point_node(pd);
viewer.setSceneData(node);
return viewer.run();
}
However, this problem crashes. I'm not sure whether I can do something like this.
I'm having a bad time with this issue because I cannot resolve it. I've designed a matrix template class and a pixel class and now I'd like to join them but I'm not been able to accomplish the task.
The error I'm having is the following:
pgm_matrix.cpp: In constructor ‘PGMmatrix::PGMmatrix(unsigned int, unsigned int)’:
pgm_matrix.cpp:13:23: error: expression list treated as compound expression in initializer [-fpermissive]
Matrix<Pixel>* m(l, h);
^
pgm_matrix.cpp:13:23: error: invalid conversion from ‘unsigned int’ to ‘Matrix<Pixel>*’ [-fpermissive]
My Pixel.hpp:
#ifndef __PIXEL_HPP__
#define __PIXEL_HPP__
class Pixel
{
private:
int posx_;
int posy_;
unsigned int intensity_;
public:
Pixel();
Pixel(int, int, unsigned int);
Pixel(Pixel const &);
~Pixel();
bool operator==(const Pixel &)const;
bool operator!=(const Pixel &)const;
Pixel const &operator=(Pixel const &);
void operator()(int, int, unsigned int);
int get_pixel_pos_x() const;
int get_pixel_pos_y() const;
unsigned int get_pixel_intensity() const;
};
#endif
My matrix.hpp:
#ifndef __MATRIX_HPP__
#define __MATRIX_HPP__
template<typename T>
class Matrix
{
private:
T** matrix_;
unsigned int rows_;
unsigned int cols_;
public:
Matrix();
Matrix(unsigned int, unsigned int);
Matrix(Matrix const &);
~Matrix();
bool operator==(const Matrix &)const;
bool operator!=(const Matrix &)const;
Matrix const &operator=(Matrix const &);
T &operator()(unsigned int, unsigned int);
T const &operator()(unsigned int, unsigned int) const;
T& data(unsigned int, unsigned int);
T const &data(unsigned int, unsigned int) const;
unsigned int const get_rows()const;
unsigned int const get_cols()const;
};
template<typename T>
Matrix<T>::Matrix() : matrix_(0), rows_(0), cols_(0)
{
}
template<typename T>
Matrix<T>::Matrix(unsigned int rows, unsigned int cols)
{
matrix_ = new T*[rows];
for(unsigned int i=0; i < rows; i++)
matrix_[i] = new T[cols];
rows_ = rows;
cols_ = cols;
}
template<typename T>
Matrix<T>::Matrix(Matrix<T> const & m_orig)
{
rows_ = m_orig.rows_;
cols_ = m_orig.cols_;
matrix_ = new T*[rows_];
for(unsigned int i=0; i < rows_; i++)
{
matrix_[i] = new T[cols_];
for(unsigned int j=0; j < cols_; j++)
matrix_[i][j]=m_orig.matrix_[i][j];
}
}
template<typename T>
Matrix<T>::~Matrix()
{
for(unsigned int i=0; i < rows_; i++)
delete matrix_[i];
delete matrix_;
rows_ = 0;
cols_ = 0;
}
template<typename T>
bool Matrix<T>::operator==(const Matrix & m)const
{
if(m.cols_ != cols_ || m.rows_ != rows_)
return false;
for(unsigned int i=0; i < rows_; i++)
{
for(unsigned int j=0; j < cols_; j++)
{
if(m.matrix_[i][j] != matrix_[i][j])
return false;
}
}
return true;
}
template<typename T>
bool Matrix<T>::operator!=(const Matrix & m)const
{
if( m == *this)
return false;
return true;
}
template<typename T>
Matrix<T> const &Matrix<T>::operator=(Matrix const & m_orig)
{
if(this != &m_orig)
{
for(unsigned int k=0; k < rows_; k++)
delete matrix_[k];
delete matrix_;
rows_ = m_orig.rows_;
cols_ = m_orig.cols_;
matrix_ = new T*[rows_];
for(unsigned int i=0; i < rows_; i++)
{
matrix_[i] = new T[cols_];
for(unsigned int j=0; j < cols_; j++)
matrix_[i][j]=m_orig.matrix_[i][j];
}
}
return *this;
}
template<typename T>
T &Matrix<T>::operator()(unsigned int i, unsigned int j)
{
return matrix_[i][j];
}
template<typename T>
T const &Matrix<T>::operator()(unsigned int i, unsigned int j) const
{
return matrix_[i][j];
}
template<typename T>
T& Matrix<T>::data(unsigned int i, unsigned int j)
{
return matrix_[i][j];
}
template<typename T>
T const &Matrix<T>::data(unsigned int i, unsigned int j) const
{
return matrix_[i][j];
}
template<typename T>
unsigned int const Matrix<T>::get_rows() const
{
return rows_;
}
template<typename T>
unsigned int const Matrix<T>::get_cols() const
{
return cols_;
}
#endif
Finally the code that fails:
#include "pgm_matrix.hpp"
#include "matrix.hpp"
#include "pixel.hpp"
PGMmatrix::PGMmatrix(unsigned int l, unsigned int h)
{
large_ = l;
height_ = h;
Matrix<Pixel>* m(l, h);
matrix_ = m;//here is the problem
}
int main()
{
PGMmatrix p(2,2);
return 0;
}
PGM_matrix.hpp:
#ifndef __PGM_MATRIX_HPP__
#define __PGM_MATRIX_HPP__
#include "matrix.hpp"
#include "pixel.hpp"
class PGMmatrix
{
private:
Matrix<Pixel>* matrix_;
unsigned int large_;
unsigned int height_;
public:
PGMmatrix();
PGMmatrix(unsigned int, unsigned int);
PGMmatrix(PGMmatrix const &);
~PGMmatrix();
bool operator==(const PGMmatrix &) const;
bool operator!=(const PGMmatrix &) const;
PGMmatrix const &operator=(PGMmatrix const &);
void operator()(int, int, Pixel);
};
#endif
to compile I do:
g++ pixel.o pgm_matrix.cpp -o pgm
How can I solve my problem?
Try using 'new' to create a new instance on the heap.
...
PGMmatrix::PGMmatrix(unsigned int l, unsigned int h)
{
large_ = l;
height_ = h;
matrix_ = new Matrix<Pixel>(l, h); // Use new, to create a new instance on the heap
}
...
Or better do not use a pointer.
...
class PGMmatrix
{
private:
Matrix<Pixel> matrix_;
...
I have some trouble with class template inheritance and operators (operator +),
please have a look at these lines:
Base vector class (TVector.h):
template<class Real, int Size>
class TVector {
protected:
Real* values;
public:
...
virtual TVector<Real, Size>& operator=(const TVector<Real, Size>& rTVector) { //WORKS
int i = 0;
while (i<Size) {
*(values+i) = *(rTVector.values+i);
i++;
}
return *this;
}
virtual TVector<Real, Size> operator+(const TVector<Real, Size>& rTVector) const {
int i = 0;
Real* mem = (Real*)malloc(sizeof(Real)*Size);
memcpy(mem, values, Size);
while (i<Size) {
*(mem+i) += *(rTVector.values+i);
i++;
}
TVector<Real, Size> result = TVector<Real, Size>(mem);
free(mem);
return result;
}
};
2D vector class (TVector2.h):
template<class Real>
class TVector2: public TVector<Real, 2> {
public:
...
TVector2& operator=(const TVector2<Real>& rTVector) { //WORKS
return (TVector2&)(TVector<Real, 2>::operator=(rTVector));
}
TVector2 operator+(TVector2<Real>& rTVector) const { //ERROR
return (TVector2<Real>)(TVector<Real, 2>::operator+(rTVector));
}
};
Test (main.cpp):
int main(int argc, char** argv) {
TVector2<int> v = TVector2<int>();
v[0]=0;
v[1]=1;
TVector2<int> v1 = TVector2<int>();
v1.X() = 10;
v1.Y() = 15;
v = v + v1; //ERROR ON + OPERATOR
return 0;
}
Compilation error (VS2010):
Error 2 error C2440: 'cast de type' : cannot convert from
'TVector<Real,Size>' to 'TVector2' ...
What is wrong here ? is there a way to do this kind of stuff ?
Just looking for a way to not redefine all my Vectors classes.
I keep searching to do it, but I will be glad to get some help from you guys.
Sorry for bad English,
Best regards.
#include <memory>
using namespace std;
template<class Real, int Size> class TVector {
protected:
Real *_values;
public:
TVector() {
// allocate buffer
_values = new Real[Size];
}
TVector(Real *prValues) {
// check first
if (prValues == 0)
throw std::exception("prValues is null");
// allocate buffer
_values = new Real[Size];
// initialize buffer with values
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] = prValues[i];
}
// Do not forget copy ctor
TVector(TVector<Real, Size> const &rTVector) {
// allocate buffer
_values = new Real[Size];
// initialize with other vector
*this = rTVector;
}
virtual ~TVector() {
delete [] _values;
}
virtual Real &operator[](int iIndex) {
// check for requested index
if (iIndex < 0 || iIndex >= Size)
throw std::exception("requested index is out of bounds");
// index is correct. Return value
return *(_values+iIndex);
}
virtual TVector<Real, Size> &operator=(TVector<Real, Size> const &rTVector) {
// just copying values
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] = rTVector._values[i];
return *this;
}
virtual TVector<Real, Size> &operator+=(TVector<Real, Size> const &rTVector) {
for (unsigned int i(0U) ; i < Size ; ++i)
_values[i] += rTVector._values[i];
return *this;
}
virtual TVector<Real, Size> operator+(TVector<Real, Size> const &rTVector) {
TVector<Real, Size> tempVector(this->_values);
tempVector += rTVector;
return tempVector;
}
};
template<class Real> class TVector2: public TVector<Real, 2> {
public:
TVector2() {};
TVector2(Real *prValues): TVector(prValues) {}
TVector2 &operator=(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator=(rTVector));
}
TVector2 &operator+=(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator+=(rTVector));
}
TVector2 operator+(TVector2<Real> const &rTVector) {
return static_cast<TVector2 &>(TVector<Real, 2>::operator+(rTVector));
}
Real &X() { return _values[0]; }
Real &Y() { return _values[1]; }
};
int main(int argc, char** argv) {
TVector2<int> v = TVector2<int>();
v[0]=0;
v[1]=1;
TVector2<int> v1 = TVector2<int>();
v1.X() = 10;
v1.Y() = 15;
v = v1;
v += v1;
v = v + v1;
return 0;
}
Some misc notes:
it's very bad that you use malloc against of new. Real can be POD only to allow vector work well in your case. Use new or provide custom creation policy if you think that malloc provides better performance on PODs. Also do not forget to use delete [] instead of free while destroying memory buffer.
It's better to perform bounds checking while overloading operator[]
for better performance use ++i instead of postfix form. In former no temporary value is created.