473,382 Members | 1,639 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Two-Dimensional Dynamic Arrays

I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:
http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.


What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.

Thanks,
Peter Olcott
Nov 25 '05 #1
60 10074
Peter Olcott wrote:
I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:

http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.

What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.


http://groups.google.com/group/comp....4f1d9bd?hl=en&

I knew I answered this once before - I think there is an FAQ as well..

Here is the example code from that posting.

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}
Nov 25 '05 #2
That looks like an excellent solution. I need absolutely top performance.
You mentioned :

some extensive matrix libraries you could use
and ones that are very efficient if the dimensions
are known.

Could you provide me a link or other reference to these?
Thanks again for your top notch assistance.

"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:q4******************************@speakeasy.ne t...
Peter Olcott wrote:
I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:

http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.

What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.


http://groups.google.com/group/comp....4f1d9bd?hl=en&

I knew I answered this once before - I think there is an FAQ as well..

Here is the example code from that posting.

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}

Nov 25 '05 #3
Oh yeah, I only need very fast addressing of the elements
of the Matrix. I will likely be moving up or down matrix rows
about five times as often as moving across matrix columns.

"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:q4******************************@speakeasy.ne t...
Peter Olcott wrote:
I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:

http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.

What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.


http://groups.google.com/group/comp....4f1d9bd?hl=en&

I knew I answered this once before - I think there is an FAQ as well..

Here is the example code from that posting.

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}

Nov 25 '05 #4
Peter Olcott wrote:
That looks like an excellent solution. I need absolutely top performance.
You mentioned :

some extensive matrix libraries you could use
and ones that are very efficient if the dimensions
are known.

Could you provide me a link or other reference to these?


Google "C++ matrix" gives a plethora of answers. Quite a while ago I
looked at some of these but I didn't get involved with the project so I
can't give you any real feedback.

What I mean by "dimensions are known" is "known at compile time". If
they are known at compile time, you don't need to perform dynamic memory
allocation and you can enable some usual compiler optimizations (like
loop unrolling).

For somthing like a 3D graphics library, this would be ideal since it
predominantly uses a 4x4 matrices (Homogeneous Coordinates) and 1x4
vectors and so much of the code can be unrolled and the compiler has a
much better chance of optimizing it.

See below, the matrix example now with the row and column sizes known.

template <typename w_elem_type, unsigned w_rows, unsigned w_columns>
class matrix
{
public:

typedef w_elem_type value_type;
static const unsigned m_columns = w_columns;
static const unsigned m_rows = w_rows;

value_type m_data[ m_rows ][ m_columns ];

typedef w_elem_type row_value_type[ m_columns ];

matrix()
: m_data()
{
}

row_value_type & operator[]( unsigned i_index )
{
return m_data[ i_index ];
}

template <typename w_elem_intype>
matrix(
const w_elem_intype (&i_array)[m_rows][m_columns]
)
{
copy_matrix( i_array );
}

template <typename w_elem_intype>
matrix(
const matrix<w_elem_intype, m_rows, m_columns > & i_array
)
{
copy_matrix( i_array.m_data );
}

template <typename w_elem_intype>
matrix & operator=(
const w_elem_intype (&i_array)[m_rows][m_columns]
)
{
copy_matrix( i_array );
return * this;
}

template <typename w_elem_intype>
matrix & operator=(
const matrix<w_elem_intype, m_rows, m_columns > & i_array
)
{
copy_matrix( i_array.m_data );
return * this;
}

private:

template <typename w_elem_intype>
void copy_matrix( w_elem_intype (&i_array)[m_rows][m_columns] )
{
w_elem_type * l_elem = & m_data[ 0 ][ 0 ];
w_elem_intype * l_from = & i_array[ 0 ][ 0 ];

for ( unsigned l_i = 0; l_i < m_columns * m_rows; ++ l_i )
{
l_elem[ l_i ] = l_from[ l_i ];
}
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },
};

int main()
{
matrix<float, 3, 4> mat1;
matrix<float, 3, 4> mat2;
matrix<float, 3, 4> mat3( array );

mat2 = mat3;

matrix<double, 3, 4> mat2d = mat2;
mat2d = mat3;

std::cout << mat2[2][3] << "\n";
}
Nov 25 '05 #5
I tested the performance of the code below and it took 150 ms,
as opposed to 4.5 ms for a conventional two dimensional array.
I am going to work on making a faster version tonight. I am
guessing that it might have to have a kludge interface:
void SetData(int ROW, int COL, UINT Data);
UINT GetData(int ROW, int COL);

"Gianni Mariani" <gi*******@mariani.ws> wrote in message
news:q4******************************@speakeasy.ne t...
Peter Olcott wrote:
I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:

http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.

What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.


http://groups.google.com/group/comp....4f1d9bd?hl=en&

I knew I answered this once before - I think there is an FAQ as well..

Here is the example code from that posting.

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}

Nov 25 '05 #6
#define UINT unsigned int
const int Width = 3000;
const int Height = 2000;
UINT Array01[Width][Height];
ArrayType2D Array02;
UINT Array03[Width][Height];
class ArrayType2D {
private:
UINT* Array;
int last_row;
public:
ArrayType2D(){ Array = new UINT [Width * Height]; };
~ArrayType2D(){ delete [] Array; };
UINT operator[](int N){ return Array[N]; };
void SetRow(int ROW) { last_row = ROW * Width; };
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
UINT GetPixel(int COL){ return Array[last_row + COL]; }
void SetPixel(int COL, UINT DATA){ Array[last_row + COL] = DATA; }
void SetPixel(int ROW, int COL, UINT DATA){ Array[(ROW * Width) + COL] = DATA; }
};

void Test04(int HEIGHT, int WIDTH) {
for (int ROW = 0; ROW < HEIGHT; ROW++) {
Array02.SetRow(ROW);
for (int COL = 0; COL < WIDTH; COL++)
Array03[ROW][COL] = Array02.GetPixel(COL);
}
}

The above code accesses a dynamic two-dimensional array
about fifteen percent faster than a conventional two-dimensional
array is accessed, if the data is to be accessed in the order
specified, moving through all the columns in a row, and then
moving to the next row. If the data is to accessed in a different
order such as moving through all the rows, and then moving to
the next column, the above code would need to be adapted.
Also one must make sure that the data is stored in the single
dimension array in the order corresponding to this different
access order.

Now if I could only have the following function
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
work with conventional Array02[ROW][COL] syntax, and find a way
to make it at least as fast as conventional array access (right now it is only
57% as fast), then I would be happier.

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:q4******************************@speakeasy.ne t...
Peter Olcott wrote:
I need to know how to get the solution mentioned below to work. The
solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below:

http://groups.google.com/group/comp....c43260a5310?hl

Another way is to create a one dimensional array and handle the
indexing yourself (index = row * row_size + col). This is readily
implemented in template classes that can create dynamically allocated
multi-dimensional arrays of any element type and number of
dimensions.

What would be the syntax for created a template that allowed a
one dimensional dynamic array, to be addressed using the conventional
syntax for accessing a two dimensional array? I am thinking that this
must be some sort of operator[] overloading.


http://groups.google.com/group/comp....4f1d9bd?hl=en&

I knew I answered this once before - I think there is an FAQ as well..

Here is the example code from that posting.

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}

Nov 26 '05 #7
Peter Olcott wrote:
#define UINT unsigned int Use a typedef here - avoid macros where possible
typedef unsigned int UINT; const int Width = 3000;
const int Height = 2000; these could be template parameters.
UINT Array01[Width][Height];
ArrayType2D Array02;
UINT Array03[Width][Height];
class ArrayType2D {
private:
UINT* Array;
int last_row;
public:
// oops - using the default copy constructor - will cause
// delete [] Array to be called multiple times (and leak)
// if the array is ever copied. (same goes for assignment
// operator.)
ArrayType2D(){ Array = new UINT [Width * Height]; };
~ArrayType2D(){ delete [] Array; };
UINT operator[](int N){ return Array[N]; };
void SetRow(int ROW) { last_row = ROW * Width; };
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
UINT GetPixel(int COL){ return Array[last_row + COL]; }
void SetPixel(int COL, UINT DATA){ Array[last_row + COL] = DATA; }
void SetPixel(int ROW, int COL, UINT DATA){ Array[(ROW * Width) + COL] = DATA; }
};

void Test04(int HEIGHT, int WIDTH) {
for (int ROW = 0; ROW < HEIGHT; ROW++) {
Array02.SetRow(ROW);
for (int COL = 0; COL < WIDTH; COL++)
Array03[ROW][COL] = Array02.GetPixel(COL);
}
}

The above code accesses a dynamic two-dimensional array
about fifteen percent faster than a conventional two-dimensional
array is accessed, if the data is to be accessed in the order
specified, moving through all the columns in a row, and then
moving to the next row. If the data is to accessed in a different
order such as moving through all the rows, and then moving to
the next column, the above code would need to be adapted.
Also one must make sure that the data is stored in the single
dimension array in the order corresponding to this different
access order.

Now if I could only have the following function
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
work with conventional Array02[ROW][COL] syntax, and find a way
to make it at least as fast as conventional array access (right now it is only
57% as fast), then I would be happier.


Did you check out the last example I posted ? Since you know the size
of your array at compile time, you can use somthing like that. On a
good optimizing compiler, this one would be just about as fast at copies
as you can get.

Is the Test04 function the only test you want ?

SetRow buys you very little in terms of performance (as implemented).

Nov 26 '05 #8

Gianni Mariani wrote:
w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}


This FAQ entry might be of interest:
http://www.parashift.com/c++-faq-lit...html#faq-13.11

See also 13.10 right above it.

Nov 26 '05 #9

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:Oc********************@speakeasy.net...
Peter Olcott wrote:
#define UINT unsigned int Use a typedef here - avoid macros where possible
typedef unsigned int UINT;
const int Width = 3000;
const int Height = 2000;

these could be template parameters.
UINT Array01[Width][Height];
ArrayType2D Array02;
UINT Array03[Width][Height];
class ArrayType2D {
private:
UINT* Array;
int last_row;
public:


// oops - using the default copy constructor - will cause
// delete [] Array to be called multiple times (and leak)
// if the array is ever copied. (same goes for assignment
// operator.)
ArrayType2D(){ Array = new UINT [Width * Height]; };
~ArrayType2D(){ delete [] Array; };
UINT operator[](int N){ return Array[N]; };
void SetRow(int ROW) { last_row = ROW * Width; };
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
UINT GetPixel(int COL){ return Array[last_row + COL]; }
void SetPixel(int COL, UINT DATA){ Array[last_row + COL] = DATA; }
void SetPixel(int ROW, int COL, UINT DATA){ Array[(ROW * Width) + COL] = DATA; }
};

void Test04(int HEIGHT, int WIDTH) {
for (int ROW = 0; ROW < HEIGHT; ROW++) {
Array02.SetRow(ROW);
for (int COL = 0; COL < WIDTH; COL++)
Array03[ROW][COL] = Array02.GetPixel(COL);
}
}

The above code accesses a dynamic two-dimensional array
about fifteen percent faster than a conventional two-dimensional
array is accessed, if the data is to be accessed in the order
specified, moving through all the columns in a row, and then
moving to the next row. If the data is to accessed in a different
order such as moving through all the rows, and then moving to
the next column, the above code would need to be adapted.
Also one must make sure that the data is stored in the single
dimension array in the order corresponding to this different
access order.

Now if I could only have the following function
UINT GetPixel(int ROW, int COL){ return Array[(ROW * Width) + COL]; }
work with conventional Array02[ROW][COL] syntax, and find a way
to make it at least as fast as conventional array access (right now it is only
57% as fast), then I would be happier.


Did you check out the last example I posted ? Since you know the size of your array at compile time, you can use somthing like
that. On a


I know it at run time, not compile time. I will take your other
suggestion (above) and repost an updated copy. The current
version seems to work just as fast as the build-in matrix, and
only lacks conventional double operator[] syntax~~~~>Data[row][col]
the next poster posted material that I will study on this. Thanks for all
your help.

good optimizing compiler, this one would be just about as fast at copies as you can get.

Is the Test04 function the only test you want ?

SetRow buys you very little in terms of performance (as implemented).

Nov 26 '05 #10

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:Oc********************@speakeasy.net...
// oops - using the default copy constructor - will cause
// delete [] Array to be called multiple times (and leak)
// if the array is ever copied. (same goes for assignment
// operator.)


//
// Array2D.h 2005-11-26 9:32 AM
//
#define UINT unsigned int
//
class ArrayType2D {
private:
int Size;
int Width;
int Height;
UINT* Array;
bool Allocated;
void Copy(ArrayType2D& Array2);
public:
ArrayType2D();
ArrayType2D(ArrayType2D& Array2) { Copy(Array2); };
~ArrayType2D() { if (Allocated) delete [] Array; };
UINT operator[](int N) { return Array[N]; };
ArrayType2D& operator=(ArrayType2D& Array2) { Copy(Array2); return *this; };
UINT* operator&() { return Array; };
UINT Get(int ROW, int COL) { return Array[ROW * Width + COL]; };
void Set(int ROW, int COL, UINT DATA) { Array[ROW * Width + COL] = DATA; }
const int size() { return Size; };
const int width() { return Width; };
const int height() { return Height; };
void Allocate(int Height, int Width);
};

void ArrayType2D::Copy(ArrayType2D& Array2) {
if (this->Allocated)
delete [] Array;
this->Width = Array2.Width;
this->Height = Array2.Height;
this->Size = Array2.Size;;
this->Array = new UINT [this->Size];
}

ArrayType2D::ArrayType2D() {
Size = 0;
Width = 0;
Height = 0;
Array = NULL;
Allocated = false;
}

inline void ArrayType2D::Allocate(int Height, int Width) {
if (Allocated)
delete [] Array;
this->Width = Width;
this->Height = Height;
this->Size = Width * Height;
this->Array = new UINT [Size];
}



Nov 27 '05 #11
This was very helpful. Not only did it provide an excellent solution,
it also analyzed all of my alternatives. If you want very high speed
and ease of use, on creating a multi-dimensional array from dynamic
memory, operator() is the way to go. I will post my latest update
shortly.

<ro**********@gmail.com> wrote in message news:11*********************@f14g2000cwb.googlegro ups.com...

Gianni Mariani wrote:
w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}


This FAQ entry might be of interest:
http://www.parashift.com/c++-faq-lit...html#faq-13.11

See also 13.10 right above it.

Nov 27 '05 #12
I goofed your code works perfectly.
I could not get the last function to compile on MSVC++ 6.0,
but after I stripped this function out and properly benchmarked
the speed it was superb. It exactly matched a statically defined
matrix. Also I got to use the double operator[], that I wanted.
Because of these reasons, I must say that your code is the best
possible code according to any possible criterion measure of
a method to create a dynamically allocated two-dimensional array.

matrix.cpp
matrix.cpp(27) : error C2265: '<Unknown>' : reference to a zero-sized array is illegal
matrix.cpp(34) : see reference to class template instantiation 'matrix<w_elem_type>' being compiled
matrix.cpp(27) : error C2265: '<Unknown>' : reference to a zero-sized array is illegal
matrix.cpp(47) : see reference to class template instantiation 'matrix<float>' being compiled
matrix.cpp(27) : error C2087: '<Unknown>' : missing subscript
matrix.cpp(47) : see reference to class template instantiation 'matrix<float>' being compiled
matrix.cpp(49) : error C2664: '__thiscall matrix<float>::matrix<float>(int,int)' : cannot convert parameter 1 from 'double [3][4]'
to 'int'
This conversion requires a reinterpret_cast, a C-style cast or function-style cast
matrix.cpp(55) : warning C4508: 'main' : function should return a value; 'void' return type assumed
#include <vector> // Line (1) of matrix.cpp identical copy of your code

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

template <typename w_Type, int w_columns, int w_rows>
matrix( const w_Type (&i_array)[w_columns][w_rows] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data( & (i_array[0][0]), & (i_array[w_columns-1][w_rows]) )
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },

};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";

}
Nov 27 '05 #13
ro**********@gmail.com wrote:
Gianni Mariani wrote:

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

This FAQ entry might be of interest:
http://www.parashift.com/c++-faq-lit...html#faq-13.11

See also 13.10 right above it.


That FAQ is a classic case of premature optimization.

It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler). Also, the compiler probably has built
in optimizations that know how to deal with stride and may get confused
when dealing with (A,B) like functor calls.

Give me an example where [A][b] is slower than (A,B) (using an decent
optimizer) and we'll see if we can fix it. Otherwise I declare the FAQ
hogwash.
Nov 27 '05 #14
Peter Olcott wrote:
I goofed your code works perfectly.
I could not get the last function to compile on MSVC++ 6.0,
MSCV6 is ancient. Do you "have to" use it ?
but after I stripped this function out and properly benchmarked
It seems like it's picking the wrong vector constructor. I think there
is another constructor vector( pointer, size ) that you could use.
the speed it was superb. It exactly matched a statically defined
matrix. Also I got to use the double operator[], that I wanted.
Because of these reasons, I must say that your code is the best
possible code according to any possible criterion measure of
a method to create a dynamically allocated two-dimensional array.


Good luck !
Nov 27 '05 #15

"Gianni Mariani" <gi*******@mariani.ws> wrote in message news:hJ******************************@speakeasy.ne t...
Peter Olcott wrote:
I goofed your code works perfectly.
I could not get the last function to compile on MSVC++ 6.0,
MSCV6 is ancient. Do you "have to" use it ?


Currently yes. The performance of your code is superb and
allows me to accomplish my execution well within my real-time
constraints. I am posting my adaptations to your code below.
All that I did is add a little more functionality.
but after I stripped this function out and properly benchmarked


It seems like it's picking the wrong vector constructor. I think there is another constructor vector( pointer, size ) that you
could use.
the speed it was superb. It exactly matched a statically defined
matrix. Also I got to use the double operator[], that I wanted.
Because of these reasons, I must say that your code is the best
possible code according to any possible criterion measure of
a method to create a dynamically allocated two-dimensional array.


Good luck !


//
// Matrix.h 2005-11-27 11:45 AM Dynamic Two-Dimensional Array Template
//
// comp.lang.c++ message from Gianni Mariani Nov 24, 2005 at 9:21 pm
// http://groups.google.com/group/comp....092f0f6c9bf13a
// Adapted by Peter Olcott resize() and operator&() added.
//
#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_rows;
t_Size m_columns;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

w_elem_type* operator&(){ return &m_data[0]; };

void resize( t_Size i_columns, t_Size i_rows );

w_elem_type * operator[]( t_Size i_index ) {
return & ( m_data[ i_index * m_rows ] );
}

};

template <typename w_elem_type>
void matrix<w_elem_type>::resize( t_Size i_columns, t_Size i_rows ) {
m_rows = i_rows;
m_columns = i_columns;
m_data.resize(i_columns * i_rows );
}

Nov 27 '05 #16

Gianni Mariani wrote:
ro**********@gmail.com wrote:
Gianni Mariani wrote:

w_elem_type * operator[]( t_Size i_index )
{
return & ( m_data[ i_index * m_rows ] );
}

This FAQ entry might be of interest:
http://www.parashift.com/c++-faq-lit...html#faq-13.11

See also 13.10 right above it.


That FAQ is a classic case of premature optimization.

It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler).


Oh really??!! Tell me then, how exactly is the compiler going to hide
the internal representiation of the matrix when you have exposed it
with the first [] operator??!! How is the compiler going to decide to
use column major instead of row major, or visa-versa, when it is the
better way to represent the matrix for the particular needs, when you
have created a dependency on row major by using the [] operator to
return rows??!!

Hint: the compiler cannot do anything to change your algorithms to a
more optomized nature for the problem you want to solve, especially
when you have created such dependencies. In fact, with your function
there not even the programmer can. Since this is perfectly laid out in
the FAQ I have to assume you never read it and/or totally missed the
point.

Also, the compiler probably has built in optimizations that know how to deal with stride and may get confused
when dealing with (A,B) like functor calls.
Hogwash. Assuming that op[][] and (x,y) would operate in the same
manner (meaning () just returned [][]) then at worst you have an inline
function call to [A+B] on your internal array. There is 0 performance
hit there (unless maybe you are in debug mode on some compilers) and
there is absolutely no difference to the compiler whatsoever.

As the FAQ says, there is never a time when () is worst than [][].

What exactly do you think the diff is between [] and () that would make
you think the compiler would get more confused over one vs. the other?

Give me an example where [A][b] is slower than (A,B) (using an decent
optimizer) and we'll see if we can fix it.
Go back and read the FAQ - it gives just such an example. Also keep
the definition of the word, "encapsulation," in mind as you read it and
try to realize what you have done by tossing out &vector[x] to
artificially create [x][y]. I mean, why even offer the protection of
the class boundary if you are going to bypass it like that??!!

Hint: not only have you created a dependency on the internals of your
own class in a rather icky way you have created a dependency on how the
std::vector class is implemented. It is highly unlikely to be
implemented in any other way but the standard does not guarantee that
behavior. Point is that dependencies now exist that never should exist
in a well structured program; these are the things that create code rot
right off the bat.

Otherwise I declare the FAQ hogwash.


That is of course your own perogative. A smarter person, however,
might decide to learn from it. I really doubt you actually read that
FAQ and comprehended what it was saying because the things you are
saying don't leave much doubt.

Nov 27 '05 #17
ro**********@gmail.com wrote:

Gianni Mariani wrote:
ro**********@gmail.com wrote:
> Gianni Mariani wrote:
>
>
>> w_elem_type * operator[]( t_Size i_index )
>> {
>> return & ( m_data[ i_index * m_rows ] );
>> }
>
>
> This FAQ entry might be of interest:
> http://www.parashift.com/c++-faq-lit...html#faq-13.11 >
> See also 13.10 right above it.
>


That FAQ is a classic case of premature optimization.

It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler).


Oh really??!! Tell me then, how exactly is the compiler going to hide
the internal representiation of the matrix when you have exposed it
with the first [] operator??!! How is the compiler going to decide to
use column major instead of row major, or visa-versa, when it is the
better way to represent the matrix for the particular needs, when you
have created a dependency on row major by using the [] operator to
return rows??!!


The FAQ makes the claim that the [][] interface is less flexible. This is
*not* true in general. The FAQ somehow seems to assume that the only way of
realizing the [][] interface is that operator[] returns an array or
something similar that exposes the internal representation of the matrix
class. However, you do not need to expose the internal representation at
all. The most easy way of doing this, would probably be a proxy:

struct matrix {

typedef unsigned long size_type;

int& operator() ( size_type row, size_type col ) {
return ( whatever(row,col) );
}

struct row_proxy {

matrix & the_matrix;
size_type the_row;

row_proxy ( matrix & A, size_type r )
: the_matrix ( A )
, the_row ( r )
{}

int& operator[] ( size_type col ) {
return( the_matrix.whatever(the_row,col) );
}

};

row_proxy operator[] ( size_type row ) {
return( row_proxy( *this, row ) );
}

// some internal representation to implement whatever goes here:
// ...

}; // matrix
Note that in expressions like A[row][col], the proxy should be optimized
away be a moderately smart optimizing compiler.
Best

Kai-Uwe Bux
Nov 27 '05 #18

Kai-Uwe Bux wrote:
ro**********@gmail.com wrote:

Gianni Mariani wrote:
ro**********@gmail.com wrote:
> Gianni Mariani wrote:
>
>
>> w_elem_type * operator[]( t_Size i_index )
>> {
>> return & ( m_data[ i_index * m_rows ] );
>> }
>
>
> This FAQ entry might be of interest:
> http://www.parashift.com/c++-faq-lit...html#faq-13.11 >
> See also 13.10 right above it.
>

That FAQ is a classic case of premature optimization.

It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler).
Oh really??!! Tell me then, how exactly is the compiler going to hide
the internal representiation of the matrix when you have exposed it
with the first [] operator??!! How is the compiler going to decide to
use column major instead of row major, or visa-versa, when it is the
better way to represent the matrix for the particular needs, when you
have created a dependency on row major by using the [] operator to
return rows??!!


The FAQ makes the claim that the [][] interface is less flexible. This is
*not* true in general. The FAQ somehow seems to assume that the only way of
realizing the [][] interface is that operator[] returns an array or
something similar that exposes the internal representation of the matrix
class.


As is done in the above code.

However, you do not need to expose the internal representation at all. The most easy way of doing this, would probably be a proxy:

struct matrix {

typedef unsigned long size_type;

int& operator() ( size_type row, size_type col ) {
return ( whatever(row,col) );
}

struct row_proxy {

matrix & the_matrix;
size_type the_row;

row_proxy ( matrix & A, size_type r )
: the_matrix ( A )
, the_row ( r )
{}

int& operator[] ( size_type col ) {
return( the_matrix.whatever(the_row,col) );
}

};

row_proxy operator[] ( size_type row ) {
return( row_proxy( *this, row ) );
}

// some internal representation to implement whatever goes here:
// ...

}; // matrix
That is an aweful lot of work just to get a particular syntax that just
ends up using the equivilant of (x,y).

Note that in expressions like A[row][col], the proxy should be optimized
away be a moderately smart optimizing compiler.


Are you sure? Have you tested this theory of yours with your own
compiler? I think you are expecting rather a lot from your compiler if
you expect that it will actually optimize out objects you tell it to
create; even more if you expect all compilers to do so. You could be
right but honestly that seems like a lot to expect, especially when the
alternative answer (different syntax, no proxy) is much more easily
optimized away and is already much more optimized than your answer
without any intelligence on behalf of the compiler.

IMO there is a balance that you need to achieve between being overly
agressive with your optimizations and depending on the compiler to do
your work for you. Adding a bunch of unnecissary code and objects to
create a specific syntax and expecting the compiler to just magically
get rid of it all is a little to far into the later area for me.

Nov 27 '05 #19
ro**********@gmail.com wrote:

Kai-Uwe Bux wrote:
ro**********@gmail.com wrote:
>
> Gianni Mariani wrote:
>> ro**********@gmail.com wrote:
>> > Gianni Mariani wrote:
>> >
>> >
>> >> w_elem_type * operator[]( t_Size i_index )
>> >> {
>> >> return & ( m_data[ i_index * m_rows ] );
>> >> }
>> >
>> >
>> > This FAQ entry might be of interest:
>> > http://www.parashift.com/c++-faq-lit...html#faq-13.11
>> >
>> > See also 13.10 right above it.
>> >
>>
>> That FAQ is a classic case of premature optimization.
>>
>> It's quite easy to turn [A][b] into (A,B) with no loss of performance
>> (on a good optimizing compiler).
>
> Oh really??!! Tell me then, how exactly is the compiler going to hide
> the internal representiation of the matrix when you have exposed it
> with the first [] operator??!! How is the compiler going to decide to
> use column major instead of row major, or visa-versa, when it is the
> better way to represent the matrix for the particular needs, when you
> have created a dependency on row major by using the [] operator to
> return rows??!!


The FAQ makes the claim that the [][] interface is less flexible. This is
*not* true in general. The FAQ somehow seems to assume that the only way
of realizing the [][] interface is that operator[] returns an array or
something similar that exposes the internal representation of the matrix
class.


As is done in the above code.


True, but somewhat irrelevant. The FAQ item 13.11 does not specifically talk
about the *above code*. Also, I do not read the claim
>> It's quite easy to turn [A][b] into (A,B) with no loss of performance
>> (on a good optimizing compiler).

as a claim about the particular implementation given up the thread.

However, you do not need to expose the internal representation at
all. The most easy way of doing this, would probably be a proxy:

struct matrix {

typedef unsigned long size_type;

int& operator() ( size_type row, size_type col ) {
return ( whatever(row,col) );
}

struct row_proxy {

matrix & the_matrix;
size_type the_row;

row_proxy ( matrix & A, size_type r )
: the_matrix ( A )
, the_row ( r )
{}

int& operator[] ( size_type col ) {
return( the_matrix.whatever(the_row,col) );
}

};

row_proxy operator[] ( size_type row ) {
return( row_proxy( *this, row ) );
}

// some internal representation to implement whatever goes here:
// ...

}; // matrix
That is an aweful lot of work just to get a particular syntax that just
ends up using the equivilant of (x,y).


Actually, one would need to do a little more to support const correct
programming. I just wanted to illustrate the concept.

However, that does not invalidate the point that [][] does not, in itself,
make a commitment to exposing the internals of a matrix class.

Note that in expressions like A[row][col], the proxy should be
optimized away be a moderately smart optimizing compiler.


Are you sure? Have you tested this theory of yours with your own
compiler?


As I discovered, this is not a theory of mine: actually it is a theory in
the FAQ. See 13.12, last paragraph. (It so happens, that the FAQ actually
covers the proxy approach. I did realize that after writing the message. So
the FAQ is not really off base. I guess, its author chose a policy of
stepwise refinement in the exposition.)
I think you are expecting rather a lot from your compiler if
you expect that it will actually optimize out objects you tell it to
create; even more if you expect all compilers to do so. You could be
right but honestly that seems like a lot to expect, especially when the
alternative answer (different syntax, no proxy) is much more easily
optimized away and is already much more optimized than your answer
without any intelligence on behalf of the compiler.
I think that optimizing away redundant temporary object presents no problem
if the functions returning/creating these objects are inlined. After
inlining, everything boils down to a local data flow analysis problem
essentially on par with any other redundant code removal, e.g., removing
unused local variables.

IMO there is a balance that you need to achieve between being overly
agressive with your optimizations and depending on the compiler to do
your work for you. Adding a bunch of unnecissary code and objects to
create a specific syntax and expecting the compiler to just magically
get rid of it all is a little to far into the later area for me.


Now, we are down to real design considerations. I tend to agree with you.
Personally, I would provide [][] only for interfacing with other code that
needs it.
Best

Kai-Uwe Bux
Nov 28 '05 #20
ro**********@gmail.com wrote:
Gianni Mariani wrote:
It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler).
Oh really??!! Tell me then, how exactly is the compiler going to hide
the internal representiation of the matrix when you have exposed it
with the first [] operator??!! How is the compiler going to decide to
use column major instead of row major, or visa-versa, when it is the
better way to represent the matrix for the particular needs, when you
have created a dependency on row major by using the [] operator to
return rows??!!


Using a proxy class.

As the FAQ says, there is never a time when () is worst than [][].
"()" won't work on legacy code, "[][]" will. "[][]" lets me use
templates that work with regular matricies and my special matrix class
as well.

What exactly do you think the diff is between [] and () that would make
you think the compiler would get more confused over one vs. the other?
That's a silly question. It all depends on how you implement [] and ().
Give me an example where [A][b] is slower than (A,B) (using an decent
optimizer) and we'll see if we can fix it.

Go back and read the FAQ - it gives just such an example.


That's not an example, I need to see results based on real compilers in
real live code. Without it, this dicussion is like pissing into a
hurricane.

Also keep the definition of the word, "encapsulation," in mind as you read it and
try to realize what you have done by tossing out &vector[x] to
artificially create [x][y]. I mean, why even offer the protection of
the class boundary if you are going to bypass it like that??!!
The proxy class gives you encapsulation (if you need it).

Hint: not only have you created a dependency on the internals of your
own class in a rather icky way you have created a dependency on how the
std::vector class is implemented. It is highly unlikely to be
implemented in any other way but the standard does not guarantee that
behavior.
I think you're mistaken. std::vector is quite well defined, objects are
contiguous.
Point is that dependencies now exist that never should exist
in a well structured program; these are the things that create code rot
right off the bat.
If this is a problem, you can break that dependantcy, even using [][].

Otherwise I declare the FAQ
hogwash.

That is of course your own perogative.


Thank you.
A smarter person, however,
might decide to learn from it. I really doubt you actually read that
FAQ and comprehended what it was saying because the things you are
saying don't leave much doubt.


You like walking on thin ice ?
Here is the same matrix code I posted earlier now using a proxy class as
I described. Now what do you have to say about the FAQ ?

#include <vector>

template <typename w_elem_type>
class matrix
{
public:
typedef int t_Size;

t_Size m_columns;
t_Size m_rows;

std::vector<w_elem_type> m_data;

matrix( t_Size i_columns = 0, t_Size i_rows = 0 )
: m_columns( i_columns ),
m_rows( i_rows ),
m_data( i_columns * i_rows )
{
}

class proxy
{
friend class matrix;

matrix & m_matrix;
t_Size m_row;

proxy(
matrix & i_matrix,
t_Size i_row
)
: m_matrix( i_matrix ),
m_row( i_row )
{
}

public:
w_elem_type & operator[]( t_Size i_column )
{
return m_matrix.m_data[
i_column + m_matrix.m_columns * m_row
];
}

private:
proxy( const proxy & );
proxy & operator=( const proxy & );
};

proxy operator[]( t_Size i_row )
{
return proxy( * this, i_row );
}

template <typename w_Type, int w_rows, int w_columns>
matrix( const w_Type (&i_array)[w_rows][w_columns] )
: m_columns( w_columns ),
m_rows( w_rows ),
m_data(
& (i_array[0][0]),
w_columns * w_rows + & (i_array[0][0])
)
{
}

};

#include <iostream>

double array[3][4] = {
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.4 },
{ 1.0, 2.0, 3.3, 4.5 },
};

int main()
{
matrix<float> mat1( 3, 4 );
matrix<float> mat2;
matrix<float> mat3( array );

mat2 = mat3;

std::cout << mat2[2][3] << "\n";
}

// note: I fixed a row/column transpose issue
Nov 28 '05 #21
Gianni Mariani wrote:
ro**********@gmail.com wrote:
Gianni Mariani wrote: [snip] Otherwise I declare the FAQ
hogwash.

That is of course your own perogative.


Thank you.
A smarter person, however,
might decide to learn from it. I really doubt you actually read that
FAQ and comprehended what it was saying because the things you are
saying don't leave much doubt.


You like walking on thin ice ?
Here is the same matrix code I posted earlier now using a proxy class as
I described. Now what do you have to say about the FAQ ?

[code snipped]

That it covers the proxy class approach in 13.12; that it agrees with your
assment about optimization of the proxy temporary; and that it discusses
the valid reasons you put forward as to when and why you might want to use
it. BTW, it also contains a reminder not to forget about const versions of
the required operators.

You still think it's hogwash?
Best

Kai-Uwe Bux

Nov 28 '05 #22
ro**********@gmail.com wrote:
Kai-Uwe Bux wrote:
ro**********@gmail.com wrote: ....
The FAQ makes the claim that the [][] interface is less flexible. This is
*not* true in general. The FAQ somehow seems to assume that the only way of
realizing the [][] interface is that operator[] returns an array or
something similar that exposes the internal representation of the matrix
class.

As is done in the above code.

However, you do not need to expose the internal representation at

.... snipped proxy example ...
}; // matrix

That is an aweful lot of work just to get a particular syntax that just
ends up using the equivilant of (x,y).


Exactly what is your issue ? The quantity of code ? If it's code
quantity, I suspect that some people will end up with more code with the
"(,)" implementation since they can't any matrix templates that use the
"[][]" syntax.

The grand-parent poster showed that the evaluation of "[][]" can be done
at exactly the same level as "(,)", which means that they are EQUAL from
a language flexibility point of view.

Note that in expressions like A[row][col], the proxy should be optimized
away be a moderately smart optimizing compiler.

Are you sure? Have you tested this theory of yours with your own
compiler?


I have, but only when it became an issue. In the example I posted
elsewhere, the gcc compiler will issue the exact same code for (,) and
[][] at "O1" level optimization. (gcc 4.0.0) The same goes for MSVC7.1.
I think you are expecting rather a lot from your compiler if
you expect that it will actually optimize out objects you tell it to
create; even more if you expect all compilers to do so. You could be
right but honestly that seems like a lot to expect, especially when the
alternative answer (different syntax, no proxy) is much more easily
optimized away and is already much more optimized than your answer
without any intelligence on behalf of the compiler.

IMO there is a balance that you need to achieve between being overly
agressive with your optimizations and depending on the compiler to do
your work for you. Adding a bunch of unnecissary code and objects to
create a specific syntax and expecting the compiler to just magically
get rid of it all is a little to far into the later area for me.


Does that mean you don't use smart pointers, inlined functions or helper
classes of any kind ?

The FAQ is wrong as it clearly makes a number of false statements.

1. "The array-of-array solution obviously works, but it is less flexible
than the operator() approach." Specifically, there are easy performance
tuning tricks that can be done with the operator() approach that are
more difficult in the [][] approach, and therefore the [][] approach is
more likely to lead to bad performance, at least in some cases."

This statement is claiming an issue with "flexibility" and
"optimization" but it clearly does not give any basis in fact.

2. "For example, the easiest way to implement the [][] ...",

Comparing "the easiest" way for option A and the "best" approach for
option B is comparing apples and oranges.

3. "Put it this way: the operator() approach is never worse than, and
sometimes better than, the [][] approach."

Patently false. If code I have uses "[][]", then quite clearly, using
the "()" approach is significantly worse.

4. "As an example of when a physical layout makes a significant
difference, ..."

This has nothing to do with the "[][]" approach vs the "(,)" approach.
As has been shown, we can easily separate the implementation from the
syntax using a proxy class. The whole paragraph is nonsensical.

5. "it has no down-side and a potential up-side"

Within entire FAQ, it has not given one thing you can do with "(,)" that
you cannot do with "[][]" yet it claims that "(,)" has a potential
upside. I still claim that there exists code that would take longer to
convert to "(,)" and will work with "[][]". I can even implement "[][]"
in tems of "(,)" which means that anything that you can do with "(,)"
can be done with "[][]".

Nov 28 '05 #23
....

You still think it's hogwash?


Yes, there is no reason to favour "(,)" over "[][]". 13.11 and 13.12
makes this distinction over and over yet provides no basis in fact that
one is superior to the other when in fact they are equivalent. So yes,
IMHO, now that I have looked at the generated code, hogwash it is since
they are 100% the same when it comes to compiled code on the 2 compilers
i tested it on.

Nov 28 '05 #24
Kai-Uwe Bux wrote:
....
As is done in the above code.

True, but somewhat irrelevant. The FAQ item 13.11 does not specifically talk
about the *above code*. Also, I do not read the claim


Ok - then the FAQ is mileading hogwash at best.
Nov 28 '05 #25
Gianni Mariani wrote:
ro**********@gmail.com wrote:
Gianni Mariani wrote:
It's quite easy to turn [A][b] into (A,B) with no loss of performance
(on a good optimizing compiler).


Oh really??!! Tell me then, how exactly is the compiler going to hide
the internal representiation of the matrix when you have exposed it
with the first [] operator??!! How is the compiler going to decide to
use column major instead of row major, or visa-versa, when it is the
better way to represent the matrix for the particular needs, when you
have created a dependency on row major by using the [] operator to
return rows??!!


Using a proxy class.

As the FAQ says, there is never a time when () is worst than [][].


IMHO, the justification for using () instead of [][] is very poor.
The scenario in which you can take advantage of the use of operator()
is one in which very very few developers would ever come across.
It's my opinion that the author of the FAQ is has had more experience
with these of the wall scenario, and is in the mistaken impression,
that others would ever need this type of requirement.

I recommend using [][] over operator(), because it's easier to read,
and to maintain.
It's also easier to port back and forth with standard C-Style 2D
arrays.

See following link for efficient implementation:
http://code.axter.com/dynamic_2d_array.h

Or check out code guru for a vector version.

Nov 28 '05 #26
Gianni Mariani wrote:
...

You still think it's hogwash?


Yes, there is no reason to favour "(,)" over "[][]". 13.11 and 13.12
makes this distinction over and over yet provides no basis in fact that
one is superior to the other when in fact they are equivalent. So yes,
IMHO, now that I have looked at the generated code, hogwash it is since
they are 100% the same when it comes to compiled code on the 2 compilers
i tested it on.


I think you are misreading the FAQ a little. It gives a (valid) reason to go
for () instead of [][]: it is *simpler* to encapsulate the innards of your
matrix class using (). Keep in mind that the FAQ is written with a newbie
reader in mind. If a newbie was to think "how would I implement a matrix
class and realize the [][] interface", the newbie would very likely end up
with code that exposes the internal representation. The FAQ is written to
make the life of this hypothetical newbie easier.

I read the remarks about performance as giving reasons as to why you want to
keep the implementation details hidden -- reasons more specific than the
general philosophical yadda yadda about encapsulation. Now, if you want to
keep encapsulation and provide the [][] interface, you will go for a proxy
class, which is considerably more tricky -- in particular if you want to
provide const versions of the interface, as well. Thus, the () interface is
the "keep it simple" approach to designing a matrix class. In my book, that
is an advantage (and not only for newbies).
Best

Kai-Uwe Bux
Nov 28 '05 #27

Kai-Uwe Bux wrote:
ro**********@gmail.com wrote:

Kai-Uwe Bux wrote:
ro**********@gmail.com wrote:

>
> Gianni Mariani wrote:
>> ro**********@gmail.com wrote:
>> > Gianni Mariani wrote:
>> >
>> >
>> >> w_elem_type * operator[]( t_Size i_index )
>> >> {
>> >> return & ( m_data[ i_index * m_rows ] );
>> >> }
>> >
>> >
>> > This FAQ entry might be of interest:
>> >
http://www.parashift.com/c++-faq-lit...html#faq-13.11
>> >
>> > See also 13.10 right above it.
>> >
>>
>> That FAQ is a classic case of premature optimization.
>>
>> It's quite easy to turn [A][b] into (A,B) with no loss of performance
>> (on a good optimizing compiler).
>
> Oh really??!! Tell me then, how exactly is the compiler going to hide
> the internal representiation of the matrix when you have exposed it
> with the first [] operator??!! How is the compiler going to decide to
> use column major instead of row major, or visa-versa, when it is the
> better way to represent the matrix for the particular needs, when you
> have created a dependency on row major by using the [] operator to
> return rows??!!

The FAQ makes the claim that the [][] interface is less flexible. This is
*not* true in general. The FAQ somehow seems to assume that the only way
of realizing the [][] interface is that operator[] returns an array or
something similar that exposes the internal representation of the matrix
class.
As is done in the above code.


True, but somewhat irrelevant. The FAQ item 13.11 does not specifically talk
about the *above code*.


Not at all irrelivant as the above is the code being discussed. If you
would like to change subject feel free to do so but don't be surprised
if you find I get bored rather quickly with such tactics.

Also, I do not read the claim
>> It's quite easy to turn [A][b] into (A,B) with no loss of performance
>> (on a good optimizing compiler).


as a claim about the particular implementation given up the thread.


Not a claim made by me and not a claim that made much sense imo.

Nov 28 '05 #28

Gianni Mariani wrote:
ro**********@gmail.com wrote:
IMO there is a balance that you need to achieve between being overly
agressive with your optimizations and depending on the compiler to do
your work for you. Adding a bunch of unnecissary code and objects to
create a specific syntax and expecting the compiler to just magically
get rid of it all is a little to far into the later area for me.


Does that mean you don't use smart pointers, inlined functions or helper
classes of any kind ?


You truely are lost. Go back to school. A -> B therefore C is not
valid logic.
Within entire FAQ, it has not given one thing you can do with "(,)" that
you cannot do with "[][]" yet it claims that "(,)" has a potential
upside. I still claim that there exists code that would take longer to
convert to "(,)" and will work with "[][]". I can even implement "[][]"
in tems of "(,)" which means that anything that you can do with "(,)"
can be done with "[][]".


You are wrong here again and again the point has just gone right past
you without one iota of understanding or even a hint that you realized
it was there. [][] by its definition creates an internal dependency
unless you create some, totally unnecissary to the task, proxy to
artificially impose the syntax paradigm in an abstract manner that in
the end just uses the more appropriate syntax of (x,y).

In other words, and hopefully ones you can understand this time as they
are in the FAQ and have been reiterated several times here, there is no
way to change the form of the matrix storage once you have created [][]
as you have done. You can't then decide that the computer would be
able to compute things faster if the matrix was stored in column major
form because all clients would then, necissarily, have to change! This
is unacceptable; a change to the private internals of a class should
NEVER affect its users. Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -
all it does is provide a particular syntax for minds too closed to
realize it is easier, and more efficient, the other way. If there is
some reason why [][] MUST be used (some screwed up 3rd party lib,
orders from on high or whatever) then you better provide it, and a
proxy (or adapter) seems like a good way of doing so, but starting from
scratch and imposing this mistake is a big mistake.

The code you provided to the OP is a perfect example of how NOT to
write good objects as it exposed the internals of not only the class
itself but it also exposed the internals of a class to which you have
no control (std::vector)...and it did so in a manner that left the
class no way to protect its *private* parts from external influence.
This just murders all reason for using objects in the first place.
Everyone does this from time to time but it is the better programmer
that can see that and learn from that mistake. Hopefully the OP is
reading this and understands better than you and can see that you made
a mistake there even if you can't (or are too proud to admit).

[][] doesn't even make sense for anything other than a vector that
contains vectors anyway - one for the vector and one for the vector it
contains at that index. There is no such operator as [][] and imposing
one simply for the sake of imposing one is just silly, pointless, and
harmful. It's rot, pure and simple.

Nov 28 '05 #29
ro**********@gmail.com wrote:

Kai-Uwe Bux wrote:
ro**********@gmail.com wrote:
>
> Kai-Uwe Bux wrote:
>> ro**********@gmail.com wrote:
>>
>> >
>> > Gianni Mariani wrote:
>> >> ro**********@gmail.com wrote:
>> >> > Gianni Mariani wrote:
>> >> >
>> >> >
>> >> >> w_elem_type * operator[]( t_Size i_index )
>> >> >> {
>> >> >> return & ( m_data[ i_index * m_rows ] );
>> >> >> }
>> >> >
>> >> >
>> >> > This FAQ entry might be of interest:
>> >> >
>> http://www.parashift.com/c++-faq-lit...html#faq-13.11 >> >> >
>> >> > See also 13.10 right above it.
>> >> >
>> >>
>> >> That FAQ is a classic case of premature optimization.
>> >>
>> >> It's quite easy to turn [A][b] into (A,B) with no loss of
>> >> performance (on a good optimizing compiler).
>> >
>> > Oh really??!! Tell me then, how exactly is the compiler going to
>> > hide the internal representiation of the matrix when you have
>> > exposed it
>> > with the first [] operator??!! How is the compiler going to decide
>> > to use column major instead of row major, or visa-versa, when it is
>> > the better way to represent the matrix for the particular needs,
>> > when you have created a dependency on row major by using the []
>> > operator to return rows??!!
>>
>> The FAQ makes the claim that the [][] interface is less flexible. This
>> is *not* true in general. The FAQ somehow seems to assume that the
>> only way of realizing the [][] interface is that operator[] returns an
>> array or something similar that exposes the internal representation of
>> the matrix class.
>
> As is done in the above code.
True, but somewhat irrelevant. The FAQ item 13.11 does not specifically
talk about the *above code*.


Not at all irrelivant as the above is the code being discussed.


Nope, the discussion actually left that code with the introduction of the
statement:
>> >> It's quite easy to turn [A][b] into (A,B) with no loss of
>> >> performance (on a good optimizing compiler).


Ever since this statement, we have been are talking about a different
implementation (at that point in the thread a hypothetical one, but as of
now, we have two drafts) where [][] is reduced to (,). Had you wanted to
return to the old code, you should not have presented your remarks as a
rebuttal to that line since critique of the old code is of no relevance for
the evaluation of this quote.
If you would like to change subject feel free to do so but don't be
surprised if you find I get bored rather quickly with such tactics.
As argued above, you are slightly mistaken about the topic. However, if you
want to discuss an implementation that has been superseeded, feel free.
However, I think that your critique of that code is not really disputed.
Also, I do not read the claim
>> >> It's quite easy to turn [A][b] into (A,B) with no loss of
>> >> performance (on a good optimizing compiler).


as a claim about the particular implementation given up the thread.


Not a claim made by me and not a claim that made much sense imo.


The statement is clearly meaningful. Whether it is true is a slightly
different matter. This pretty much depends on how you understand "easy". If
you consider writing a proxy class like the two presented complicated, you
will consider the statement false -- although you should agree to the
weaker version:

It's *possible* to turn [A][b] into (A,B).

This possibility has been demonstrated.
Best

Kai-Uwe Bux
Nov 28 '05 #30

Kai-Uwe Bux wrote:
>> >> It's quite easy to turn [A][b] into (A,B) with no loss of
>> >> performance (on a good optimizing compiler).
The statement is clearly meaningful. Whether it is true is a slightly
different matter. This pretty much depends on how you understand "easy". If
you consider writing a proxy class like the two presented complicated, you
will consider the statement false -- although you should agree to the
weaker version:

It's *possible* to turn [A][b] into (A,B).

This possibility has been demonstrated.


Actually, what your proxy class did was to demonstrate that () could be
turned into [][] as what your proxy did was to create an adapter to
call () with the [][] interface...in other words the interface was
changed from () TO [][], not the other way. This is a rather important
distinction as it shows which was the more natural way to provide a
service. It also did a good job of illistrating how this added several
layers of totally unnecissary complexity.

At any rate, your assertion is without meaning. Of course it is
possible to call () with [][] or [][] with (). This does not mean the
two are equivilent in nature. Any claim otherwise is a failure in
logic. It is also possible to make operator * mean addition in C++,
and much more simply in fact. Is it useful? Is it introducing or
removing problems? Those are the questions to ask yourself.

No matter how you choose to alter the topic of discussion it was
certainly never asserted by anyone that it was not possible to call one
function with another. The *possibility* of generating the classes and
functions necissary to provide an interface for an artificially imposed
syntax was NEVER disputed. There is no end to the stupid things that
are *possible* to do. If that is all you have left to cling to then
there is nothing left to argue.

Nov 28 '05 #31

Axter wrote:
I recommend using [][] over operator(), because it's easier to read,
and to maintain.
It's also easier to port back and forth with standard C-Style 2D
arrays.

See following link for efficient implementation:
http://code.axter.com/dynamic_2d_array.h


This is just a reiteration of the original code. At least in this case
though you aren't exposing internals of a class you have no control
over but only your own. The above class has no purpose. It protects
nothing. m_data may as well be public. That class doesn't even check
its inputs. The only thing you could say it does is keep track of its
2d dimensions...but you could do that with a struct.

Since it exposes its internal data to the public and provides no
protected interface to that data this class has next to no
encapsulation. This means all clients have to manage everything.
Better yet, you provide no way to get at necissary information that
would allow the clients to make sure they don't send bad input to the
class...but the class doesn't make sure its inputs are valid...in other
words the little encapsulation the class does offer is actually bad as
it means every client must also keep its own copy of the array bounds.

Since each client has to track its own copies of the bounds and do its
own error checking to make sure never to violate the exposed internals
of the class, this class is not only unnecissary it is also a very
inefficient implementation - a public pointer would be more efficient
and easier to maintain. Do some casts and get your [][] syntax...

Not very convincing.

About [][] being easier to read. Well that is a stylistic preference
but keep in mind two things:

1) In math the syntax is (a,b) - though usually subscripted.
2) Is it really that much easier to read that the added complexity
necissary to implement it adiquately is warranted?

About it being easier to maintain...I think you will need to elaborate
more on this idea as I see your above cited example as being an
absolute maintanence nightmare. Sure, the class is simple but its
clients are going to get really messy.

Nov 28 '05 #32

Kai-Uwe Bux wrote:
reasons more specific than the
general philosophical yadda yadda about encapsulation.


Heh...it's no wonder I run into so much code rot in the real world.
Encapsulation is more that "general philisophical yadda yadda." It is
the sole purpose of classes and the very foundation of OOP. A class
that doesn't encapsulate its data is like a cell with no wall. When a
cell has no wall its insides just kind of meander about to god only
knows where....sort of like sauce in a bowl of spaghetti.

I can't believe I wasted so much time arguing with people that don't
even understand the importance of so simple a concept. If you don't
understand this concept and its importance then there is no way you can
understand the reasoning in the FAQ entry I cited or why returning
&array[x] is horrid.

No wonder...

hehehehe I've been bashing my head against the brick wall of
newbieville.

Nov 28 '05 #33
ro**********@gmail.com wrote:
Gianni Mariani wrote: .... You truely are lost. Go back to school. A -> B therefore C is not
valid logic.
Another fact free statement, let's see how many facts we can actually
find in this posting.

Within entire FAQ, it has not given one thing you can do with "(,)" that
you cannot do with "[][]" yet it claims that "(,)" has a potential
upside. I still claim that there exists code that would take longer to
convert to "(,)" and will work with "[][]". I can even implement "[][]"
in tems of "(,)" which means that anything that you can do with "(,)"
can be done with "[][]".

You are wrong here ...


This is gong to be rich.
... again and again the point has just gone right past
you without one iota of understanding or even a hint that you realized
it was there. [][] by its definition creates an internal dependency
unless you create some, totally unnecissary to the task, proxy to
artificially impose the syntax paradigm in an abstract manner that in
the end just uses the more appropriate syntax of (x,y).
"unnecissary" - I'm not sure I think you know what that means.

Wether somthing is needed is determined by design.

In other words, and hopefully ones you can understand this time as they
are in the FAQ and have been reiterated several times here, there is no
way to change the form of the matrix storage once you have created [][]
as you have done.
.... Give me any implementation that takes a (,) and it can be turned
into a [][] with no loss in performance. They ARE THE SAME THING except
that [][] is more commonly found in numeric code written in C or C++
which means less porting, easier templates, yadda yadda, There is NO
GOOD REASON to use (,).
... You can't then decide that the computer would be
able to compute things faster if the matrix was stored in column major
form because all clients would then, necissarily, have to change! This
is unacceptable; a change to the private internals of a class should
NEVER affect its users.
Again, the only logical way you can get to this conclusion is if there
was somthing different between [][] and (,). You have already admitted
that there is no essential difference so another fact free statement.
... Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -
(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.
all it does is provide a particular syntax for minds too closed to
realize it is easier, and more efficient, the other way.
a) easier is a matter of opinion
b) efficient is a fallacy

More fact free statements.
... If there is
some reason why [][] MUST be used (some screwed up 3rd party lib,
orders from on high or whatever)
How about the C++ standard ?

float matricks[3][4];

.... try referencing matricks using (,).

There is a plethora of already written code that uses [][]. Unless
there is a good reason to change it, then don't.
... then you better provide it, and a
proxy (or adapter) seems like a good way of doing so, but starting from
scratch and imposing this mistake is a big mistake.
Consider this:
template <typename T>
struct matrix_traits;

template <typename w_Type >
struct matrix_traits< matrix< w_Type > >
{
typedef w_Type value_type;

static unsigned rows(
const matrix< w_Type > & i_matrix
)
{
return i_matrix.m_rows;
}

static unsigned columns(
const matrix< w_Type > & i_matrix
)
{
return i_matrix.m_columns;
}
};

template <typename w_Type, int w_rows, int w_columns>
struct matrix_traits< w_Type [w_rows][w_columns] >
{
typedef w_Type value_type;

static unsigned rows(
const w_Type (&i_array)[w_rows][w_columns]
)
{
return w_rows;
}

static unsigned columns(
const w_Type (&i_array)[w_rows][w_columns]
)
{
return w_columns;
}
};
template <typename TRESULT, typename T0, typename T1>
void add_matrix(
TRESULT & result,
const T0 & i_arg0,
const T1 & i_arg1
)
{
assert(
matrix_traits<TRESULT>::rows(result)
== matrix_traits<T0>::rows(i_arg0)
);
assert(
matrix_traits<T1>::rows(i_arg1)
== matrix_traits<T0>::rows(i_arg0)
);
assert(
matrix_traits<TRESULT>::columns(result)
== matrix_traits<T0>::columns(i_arg0)
);
assert(
matrix_traits<T1>::columns(i_arg1)
== matrix_traits<T0>::columns(i_arg0)
);

for (
unsigned l_row = matrix_traits<T0>::rows(i_arg0);
0 < l_row --;
)
{
for (
unsigned l_column = matrix_traits<T0>::columns(i_arg0);
0 < l_column --;
)
{
result[ l_row ][ l_column ] =
i_arg0[ l_row ][ l_column ]
+ i_arg0[ l_row ][ l_column ];
}
}
}

void add_test(
double (&ar)[3][4],
const double (&a0)[3][4],
const double (&a1)[3][4]
)
{
add_matrix( ar, a0, a1 );
}

void add_test(
matrix<float> & ar,
const double (&a0)[3][4],
const double (&a1)[3][4]
)
{
add_matrix( ar, a0, a1 );
}

The "add_matrix" method works equally as well with the matrix class as
it would a POD matrix. This would not be true if the matrix class
depended on (,) as the indexing syntax. This is a very significant issue.

The code you provided to the OP is a perfect example of how NOT to
write good objects as it exposed the internals of not only the class
itself but it also exposed the internals of a class to which you have
no control (std::vector)...and it did so in a manner that left the
class no way to protect its *private* parts from external influence.
This just murders all reason for using objects in the first place.
FYI, I was not going for the best code, I was going for quick example of
how you can make a dynamically sized matrix in the same spirit as
std::vector. Your points are well taken. However, you can complain
about code posted by others but you seem unwilling to post corrected
code. If these issues irk you so much, fix it.
Everyone does this from time to time but it is the better programmer
that can see that and learn from that mistake. Hopefully the OP is
reading this and understands better than you and can see that you made
a mistake there even if you can't (or are too proud to admit).
You're such a good programmer, we know, show us already.

[][] doesn't even make sense for anything other than a vector that
contains vectors anyway - one for the vector and one for the vector it
contains at that index.
Fact free statement, please explain why it makes no sense.
... There is no such operator as [][]
Yep, right again. That is 2 "[]" operators. The point is ?
... and imposing
one simply for the sake of imposing one is just silly, pointless, and
harmful.
You keep on saying it's an imposition to use [][], however, I have
stated at least 3 times now that it does make sense for legacy code and
generic programming, I have even given you an example of code that works
for both regular POD matrix and the dynamic matrix example I showed
earlier in this post. You have never refuted these statements, yet you
cast the whole idea as "rot".
... It's rot, pure and simple.


Is that a technical phrase ?
Nov 28 '05 #34
ro**********@gmail.com wrote:

Kai-Uwe Bux wrote:
>> >> >> It's quite easy to turn [A][b] into (A,B) with no loss of
>> >> >> performance (on a good optimizing compiler).
The statement is clearly meaningful. Whether it is true is a slightly
different matter. This pretty much depends on how you understand "easy".
If you consider writing a proxy class like the two presented complicated,
you will consider the statement false -- although you should agree to the
weaker version:

It's *possible* to turn [A][b] into (A,B).

This possibility has been demonstrated.


Actually, what your proxy class did was to demonstrate that () could be
turned into [][] as what your proxy did was to create an adapter to
call () with the [][] interface...in other words the interface was
changed from () TO [][], not the other way.


This, I guess is an ambiguity in English. Gianni Mariani clearly meant that
the user could write

A[row][col]

and this expression would, by means of proxy magic, eventually result in a
call of A(row,col). Whether you want to call that a transformation from (,)
to [][] or a transformation from [][] to (,) seems a matter of perspective.
This is a rather important
distinction as it shows which was the more natural way to provide a
service. It also did a good job of illistrating how this added several
layers of totally unnecissary complexity.
"Several layers" is an exaggeration.

Whether the added complexity is unnecessary cannot be answered in the
absolute. Very much, depends on the context. However, I would agree that
one should not implement the proxy layer without good reason.

The stronger claim that was made is that this is easy (somewhat a matter of
opinion, taste, and cultural background) and can be done without
performance penalty (a purely technical claim also stated in the FAQ
[13.12]). I think, it is "easy" (some 40 lines of code for a little bit of
syntactic sugar is not that big a deal to me). Moreover, Gianni Mariani has
confirmed that, with modern compilers, one does not need to fear a loss in
performance. So, although we may have to agree to disagree on the easyness
part, there is a confirmation for the claim concerning performance.

At any rate, your assertion is without meaning. Of course it is
possible to call () with [][] or [][] with ().
So, you concede that it is true. Well, then it is, a fortiori, not without
meaning. If, however, you would be using the word "meaning" synonymous with
"relevance", then you have a point :-)

The stronger claim, however, that proxies are easy to implement and can be
done without performance penalty, is clearly relevant. In particular, it
implies that the FAQ advice should be taken with a grain of salt as the
purely technical discussion of performance in the FAQ applies strictly to
simple minded, not proxy based implementations of the [][] interface (such
as the one first given to the OP).

This does not mean the two are equivilent in nature.


I don't think, I claimed that.
However, this sub-thread started with a slight disagreement about what would
constittue "changing the subject". I feel that that point became somewhat
mood.

In any case, I share your sentiment about the first matrix class as
presented to the OP.

As for proxy classes there are two established issues in this thread:

a) easyness.
b) performance.

I would suggest to ditch (a): it is clear that proxy classes add complexity.

I would suggest to declare that (b) should be re-evaluated when more data
points become available.

Finally, I would also like to open a new angle on proxies:

c) which opportunities do proxies as part of a matrix interface offer?

I think that it makes perfect sense to have a matrix class define types
row_vector and col_vector and to provide full fledged expression
templates / proxies that allow you to address the rows and columns in a
matrix. What I am thinking of is something like this: you could express a
row-operation as

A[i] += 2*A[j];

This, of course, will not work for columns. So, I would suggest member
functions

row_vector_proxy row ( size_type );

and

col_vector_proxy col ( size_type );

Thus, the above becomes

A.row(i) += 2 * A.row(j);

and swapping two columns could be done via

std::swap( A.col(i), A.col(j) );

At some point, methinks, this can reduce the overall complexity of a matrix
class interface. In my own matrix class, I have member functions for
elementary row/col operations and row and column swaps. Maybe, proxies
actually could be useful in order to reduce complexity.
Best regards

Kai-Uwe Bux
Nov 28 '05 #35
ro**********@gmail.com wrote:

Kai-Uwe Bux wrote:
reasons more specific than the
general philosophical yadda yadda about encapsulation.
Heh...it's no wonder I run into so much code rot in the real world.
Encapsulation is more that "general philisophical yadda yadda." It is
the sole purpose of classes and the very foundation of OOP. A class
that doesn't encapsulate its data is like a cell with no wall. When a
cell has no wall its insides just kind of meander about to god only
knows where....sort of like sauce in a bowl of spaghetti.


Exactly, and the FAQ item I referred to provided additional reasons that are
more specific in that they apply to matrix classes proper but not to all
classes. Here is the complete sentence:
I read the remarks about performance as giving reasons as to why you want
to keep the implementation details hidden -- reasons more specific than
the general philosophical yadda yadda about encapsulation.


I can't believe I wasted so much time arguing with people that don't
even understand the importance of so simple a concept. If you don't
understand this concept and its importance then there is no way you can
understand the reasoning in the FAQ entry I cited or why returning
&array[x] is horrid.

No wonder...

hehehehe I've been bashing my head against the brick wall of
newbieville.


Why do you insult me?
Regards

Kai-Uwe Bux
Nov 28 '05 #36

ro**********@gmail.com wrote:
Axter wrote:
I recommend using [][] over operator(), because it's easier to read,
and to maintain.
It's also easier to port back and forth with standard C-Style 2D
arrays.

See following link for efficient implementation:
http://code.axter.com/dynamic_2d_array.h
This is just a reiteration of the original code. At least in this case
though you aren't exposing internals of a class you have no control
over but only your own. The above class has no purpose. It protects
nothing. m_data may as well be public. That class doesn't even check
its inputs. The only thing you could say it does is keep track of its
2d dimensions...but you could do that with a struct.

Since it exposes its internal data to the public and provides no
protected interface to that data this class has next to no
encapsulation. This means all clients have to manage everything.
Better yet, you provide no way to get at necissary information that
would allow the clients to make sure they don't send bad input to the
class...but the class doesn't make sure its inputs are valid...in other
words the little encapsulation the class does offer is actually bad as
it means every client must also keep its own copy of the array bounds.

Since each client has to track its own copies of the bounds and do its
own error checking to make sure never to violate the exposed internals
of the class, this class is not only unnecissary it is also a very
inefficient implementation - a public pointer would be more efficient
and easier to maintain. Do some casts and get your [][] syntax...

Not very convincing.


The purpose of the class, is not to provide bounds checking or extra
encapsolation.
It's purpose is to provide a basic generic frame work for an efficient
dynamic 2D array class that can be access using normal C-Style syntax.

Classes that attempt to do everything, end up doing nothing very
efficient.

About [][] being easier to read. Well that is a stylistic preference
but keep in mind two things:

1) In math the syntax is (a,b) - though usually subscripted.
Keep in mind, that C/C++ does not use that type of syntax, and I think
that idea is as bad as trying to make C++ code like BASIC.
Adding different syntax for contrived reasones, only serves to make the
code harder to read and understand. Stick with the KISS (Keep It
Simple Stupid) approach.
About it being easier to maintain...I think you will need to elaborate
more on this idea as I see your above cited example as being an
absolute maintanence nightmare. Sure, the class is simple but its
clients are going to get really messy.


I think you should provide an example as how this simple generic class
would be a nightmare to maintain, anymore then using a generic class
like std::vector.

IMHO, the idea of using operator() for a 2D array is a very bad idea,
and does not work well with the generic programming model. There is no
real legitimate reason for promoting operator() use over [][] in
generic programming.
On this matter, the C++ FAQ is very wrong.

Nov 28 '05 #37

Axter wrote:
I think you should provide an example as how this simple generic class
would be a nightmare to maintain, anymore then using a generic class
like std::vector.


I don't. I think it sufficient to point out that, among other
important things, std::vector provides access to its bounds and your
class does not. Therefore every client of your class must have a copy
of the array boundaries while with std::vector they would not.
std::vector also does significantly more than your class including
growing in size and providing methods for sorting, searching, etc.
Your class not only doesn't do much, it doesn't do anything. It would
be MUCH more effecient to implement what you are doing with a simple
pointer and some casts.

I'll let the FAQ stand on its own. I don't need to defend it and it's
obvious to me now that I am arguing with a pack of newbies that refuse
to learn anything valueable. The FAQ was written by people smarter
and/or more experienced than either of us; I choose to learn from such
people so as to improve my efficiency as a professional
developer...especially when what they say is so well stated and
obviously true...and I am actually more convinced of that now since the
only ones saying I'm wrong don't seem to understand basic concepts
and/or have gotten completely lost by the topic of discussion.

Nov 28 '05 #38

ro**********@gmail.com skrev:
Axter wrote:
I think you should provide an example as how this simple generic class
would be a nightmare to maintain, anymore then using a generic class
like std::vector.


[snip]
I'll let the FAQ stand on its own. I don't need to defend it and it's
obvious to me now that I am arguing with a pack of newbies that refuse
to learn anything valueable. The FAQ was written by people smarter
and/or more experienced than either of us; I choose to learn from such
people so as to improve my efficiency as a professional
developer...especially when what they say is so well stated and
obviously true...and I am actually more convinced of that now since the
only ones saying I'm wrong don't seem to understand basic concepts
and/or have gotten completely lost by the topic of discussion.


Let me step in. So far as I see this thread is a rather bad attempt to
defend a position in the C++-faq. You seem to ignore the advice from
Gianni and you fail to respond to his quite reasonable arguments for
using operator []: namely that this allows reuse of existing code, e.g.
in a template library.
The C++ faq is very well written and invaluable for newbies and
programmers in the beginning of their C++ career, but that does not
mean that it is without flaws (*) or that it does not cut corners on
some of the more advanced stuff.
I've "known" Mariani on this newsgroup for quite some time now; he is
certainly not a newbie and is quite capable of writing and
understanding C++. If only you did care to read his posts and
understand them, this would be clear to you. I would recommend you to
cut down on your ego and learn from him.

/Peter

* If you go to the C++ faq you will find a list of recent changes.
Among them is a correction from ... Gianni Mariani.

Nov 28 '05 #39

ro**********@gmail.com wrote:
Axter wrote:
I think you should provide an example as how this simple generic class
would be a nightmare to maintain, anymore then using a generic class
like std::vector.
I don't. I think it sufficient to point out that, among other
important things, std::vector provides access to its bounds and your
class does not. Therefore every client of your class must have a copy
of the array boundaries while with std::vector they would not.
std::vector also does significantly more than your class including
growing in size and providing methods for sorting, searching, etc.
Your class not only doesn't do much, it doesn't do anything. It would
be MUCH more effecient to implement what you are doing with a simple
pointer and some casts.


I've been programming for almost 20 years, and I'm 2nd ranking C++
expert in the Experts-Exchange
(http://www.experts-exchange.com/Cplusplus)
I'm also a frequent contributor to Code-Guru C++/VC++ topic area as
well as Code Project Visual C++ and STL topic area.
If this is what you consider a newbie, then I guess I'm a newbie.

What ever label you choose to give me or others, does not take away
from the fact that you're argument is flawed and very incorrect.
It's been my experience that debaters that result in name calling do
so, because they don't have a legitimate argument to put forth.

I believe this is the case here.
You've only attempted to side track the real issue with petty
critiques that have nothing to do with the main point.

I'll let the FAQ stand on its own. I don't need to defend it and it's
obvious to me now that I am arguing with a pack of newbies that refuse
to learn anything valueable. The FAQ was written by people smarter
and/or more experienced than either of us;


Please speak for yourself. Your level of experience may coincide with
the above comment, but I would make no such assumptions with my
experience and expertise.
Moreover, even the best experts in any field make mistakes.
IMHO, this part of the C++ FAQ is incorrect.

Nov 28 '05 #40

Axter wrote:
ro**********@gmail.com wrote:
Axter wrote:
I think you should provide an example as how this simple generic class
would be a nightmare to maintain, anymore then using a generic class
like std::vector.
I don't. I think it sufficient to point out that, among other
important things, std::vector provides access to its bounds and your
class does not. Therefore every client of your class must have a copy
of the array boundaries while with std::vector they would not.
std::vector also does significantly more than your class including
growing in size and providing methods for sorting, searching, etc.
Your class not only doesn't do much, it doesn't do anything. It would
be MUCH more effecient to implement what you are doing with a simple
pointer and some casts.


I've been programming for almost 20 years, and I'm 2nd ranking C++
expert in the Experts-Exchange
(http://www.experts-exchange.com/Cplusplus)
I'm also a frequent contributor to Code-Guru C++/VC++ topic area as
well as Code Project Visual C++ and STL topic area.
If this is what you consider a newbie, then I guess I'm a newbie.


Well, I don't really pay attention to "credentials". I've been
published too. BFD. My analysis of your class stands. If you could
counter that analysis I guess you would have. Appeal to authority
isn't good enough in my book.
What ever label you choose to give me or others, does not take away
from the fact that you're argument is flawed and very incorrect.
It's been my experience that debaters that result in name calling do
so, because they don't have a legitimate argument to put forth.

I believe this is the case here.
You've only attempted to side track the real issue with petty
critiques that have nothing to do with the main point.


They actually have everything to do with the main point. Your class
design is fundamentally flawed. You offered it as an example of how to
implement [][] and the plain fact is that your implementation is broken
in ways that are very fundamental and very basic. Your attempt at
creating the [][] syntax just to have that syntax led you down a path
that resulted in code that had fundamental flaws in it destined to
create problems in any decently sized project; my analysis (or
critique) of these things speak directly to the issue. I have
explained those ways already and you fail to answer to them but instead
have decided to claim I sidetracked the issue.

Maybe my claim that you're a newbie was a little unwaranted but the
class you provided as an example of how to do something right as a
counter to the FAQ entry is very newbieish and flawed.

Nov 29 '05 #41

Gianni Mariani wrote:
... Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -


(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.


I can pretty much answer your entire post right here as this is the
main point. I have already stated that legacy code is an issue. There
is no nice way to deal with code that needs [][] especially if it was
written with C style arrays in mind. Your template classes look nice
but I believe your use of [][] was a mistake.

Now, I have already stated that legacy code or orders from on high are
one thing, but designing a mistake like this in from scratch is a big
mistake. Your template class works great and is rather efficient for C
style array and with vectors of vectors. A C function will still of
course not be able to deal with vectors of vectors so if you have to
use one you are already up shit creek.

But lets look at it from a fresh view kind of standpoint. Being as we
can set asside the issue of legacy code that depends on C style arrays
we can evaluate each implementation's merrit without artificial
requirements. When we are designing from scratch we want robust code
that is also fast. Robust in that it verifys inputs and makes sure
that clients don't try to do something they shouldn't (the argument for
robust code is pretty well known and accepted so I won't go there). We
want fast in both development and testing time as well as run time;
this means we want to do as little as possible to get the job done.

We can create our general functions with the [][] syntax or () syntax -
or with a standard function for that matter. C arrays are obviously
better suited for the [][] syntax so it might seem like the best
choice. However, objects appear to be better suited for the () syntax
for reasons that have already been gone over several times -> The only
protected way to provide [][] in an object is to create an adapter for
the () or function call interface; we can create a simpler
implementation but we expose the internals of the class and basically
ruin the whole purpose of a class so that our array would be better
just exposed and used normally (the only reasons to create an object
class is because of the protections such constructs offer - otherwise
simple functions and PODs are much better).

So, someone already showed us some basics of what would be needed to
implement the () to [][] adapter for an object and still let the class
construct do its job; it was comparitively involved and it wasn't even
finished. So, how would you make an adapter for the other method? I
myself might provide something as simple as:

template<typename T>
class CArrAdapter
{
T * data;
int col_num;
int row_num;
public:
CArrAdapter(T * d, int c, int r) : data(d), col_num(c), row_num(r) {}
T operator () (int i, int j) { if ( i > row_num || j > col_num) throw
something; return *(data + i * col_num + j); }
};

That to me looks a lot simpler, smaller, easier to test and validate,
and just all around better than the adapter required to change () into
[][].

The question now comes of "legacy" code. First off it seems rather
established that we are talking about something similar to the template
classes you posted and not something in C. The reason is simple - you
can't pass a C++ object into a C function that expects an array anyway
- no way to do it (well some very platform specific stuff might work
but lets stay simple).

The thing I like to do with "legacy" code is replace it. Not
immediately of course as time is an issue usually but as things go by I
like to fix little problems I see and eventually totally replace all
"legacy" code with something better - if necissary. So, do we want to
be stuck forever with the [][] syntax or would we eventually like to
replace it with something that is simpler but still robust? This is
when that nice () to [][] adapter comes into play nicely. Use it when
I have to, write everything new with the "better" design, and
eventually the "legacy" code and the adapter go the way of the dodo -
that includes things like those templates you posted though just going
through and changing them might be enough. This is why I feel the
"legacy" code argument is rather weak - I don't like keeping legacy
code if I don't like it and can think of something better...especially
if it gets rid of a lot of nastyness like the breaking of class
boundaries. I especially don't like to stick my design to it.

Now, you also made the claim more recently that you original code post
was not meant to be a *good* example but just a quicky. That is
reasonable, but I for one took it as your real advice and I think the
OP did as well. So then I am gathering that you see the flaw in
returning &vect[i] and agree that it is a problem.

At this point it is assumed that an adapter must be created either
for the object or for the array. I can't think of a decent alternative
and the only alternative offered is fundamentally flawed - you yourself
seem to now be sharing this view as you are now saying your code was
just a "quicky". So, since an adapter is required I say that the
choice is then based on which is the simpler. I would also have the
goal in mind to phaze out the use of C arrays and replace them with C++
objects eventually. My choice at that point is a given.

Now you have my logic on the matter. Either you understand or you
don't. Either you agree or you don't. I don't have any more time to
discuss this right now...the weekend is over.

Nov 29 '05 #42
ro**********@gmail.com wrote:
Gianni Mariani wrote:
... Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -
(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.


I can pretty much answer your entire post right here as this is the
main point. I have already stated that legacy code is an issue. There
is no nice way to deal with code that needs [][] especially if it was
written with C style arrays in mind. Your template classes look nice
but I believe your use of [][] was a mistake.

Now, I have already stated that legacy code or orders from on high are
one thing, but designing a mistake like this in from scratch is a big
mistake. Your template class works great and is rather efficient for C
style array and with vectors of vectors. A C function will still of
course not be able to deal with vectors of vectors so if you have to
use one you are already up shit creek.

But lets look at it from a fresh view kind of standpoint. Being as we
can set asside the issue of legacy code that depends on C style arrays
we can evaluate each implementation's merrit without artificial
requirements.


That is not an artificial requirement, and any experience programmer
would tell you that.
Legacy code is a very real world, and very common requirement for day
to day coding.
Often when adding new modifications to legacy code, you're force to use
the current interface, which would exclude using operator().
It would be a terrible idea to introduce the use of operator() in one
part of the source code, and use [][], in another part of the same
source code.
And changing the entire code to use operator() would more then likely
introduce many bugs, that wouldn't get picked up until your customer
reports it.
It's an equally bad idea to say it's better to use raw pointers, which
would also have a high chance of introducing new bugs.
It's safer to use a wrapper class, like the one I posted.

The main purpose for the wrapper class is to show how to efficiently
implement a dynamic 2D array class using [][] interface.
I intentionally did not add any extra bounds checking code, because
that would have created a distraction from the main implementation I
was trying to convey.
Any beginner can add GetX and GetY functions to this class:
int GetRow() const{return m_row;}
int GetCol() const{return m_col;}

If you don't know how to do this, then you shouldn't even be looking at
this class.
http://code.axter.com/dynamic_2d_array.h

When we are designing from scratch we want robust code
that is also fast. Robust in that it verifys inputs and makes sure
that clients don't try to do something they shouldn't (the argument for
robust code is pretty well known and accepted so I won't go there). We
want fast in both development and testing time as well as run time;
this means we want to do as little as possible to get the job done.

We can create our general functions with the [][] syntax or () syntax -
or with a standard function for that matter. C arrays are obviously
better suited for the [][] syntax so it might seem like the best
choice. However, objects appear to be better suited for the () syntax
for reasons that have already been gone over several times -> I completely disagree. I've only read contrived justifications for
using () syntax, that have nothing to do with generic programming, or
with 99.99% of C++ development.
Example:
Previous Post:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>

Tell me then, how exactly is the compiler going to hide the internal representiation of
the matrix when you have exposed it with the first [] operator??!!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>


99.99% of developers would never ever need to get the internal
representation of the matrix, and would never need to change col for
row within the matrix.
For those very few developers that do need to perform such optimization
methods, most likely their implementation will only work efficiently in
a particular OS and hardware settings.
It would not be generic implementation, that you could port to other OS
or even other hardware using the same OS.
A developer would have a better chance of winning the lottery, then
ever having to use these optimization methods.

The justification given in the C++ FAQ and the justification given in
this thread, are very weak at best, and play no part in generic C++
programming.
protected way to provide [][] in an object is to create an adapter for
the () or function call interface; we can create a simpler
implementation but we expose the internals of the class and basically
ruin the whole purpose of a class so that our array would be better
just exposed and used normally (the only reasons to create an object
class is because of the protections such constructs offer - otherwise
simple functions and PODs are much better).
There are many, many reasons to create an object class, and protection
is only one of many.
The dynamic_2d_array class is type safe, and reduces the chance of
memory leaks compare to using pointers.
Other then using pointers, you can not create a dynamic 2D array using
POD concrete types.
It's far safer to use the wrapper class.

So, someone already showed us some basics of what would be needed to
implement the () to [][] adapter for an object and still let the class
construct do its job; it was comparitively involved and it wasn't even
finished. So, how would you make an adapter for the other method? I
myself might provide something as simple as:

template<typename T>
class CArrAdapter
{
T * data;
int col_num;
int row_num;
public:
CArrAdapter(T * d, int c, int r) : data(d), col_num(c), row_num(r) {}
T operator () (int i, int j) { if ( i > row_num || j > col_num) throw
something; return *(data + i * col_num + j); }
};

That to me looks a lot simpler, smaller, easier to test and validate,
and just all around better than the adapter required to change () into
[][].

There are so many things wrong with the above class.
1. The above class is not safe as it can be since col_num and row_num
are not constant. Clearly they should be constant, since there's no
implementation for changing the size of the array.

2. Your class can not be used if the object is constant, since you
failed to provide a constant version for operator().

3. Your implementation is returning by value, which makes it very
inefficient.

4. The class also fails to test that the input pointer is not NULL.
(should have assertion).

5. Since your class is taking int instead of size_t, your class can
also fail if the input arguments are negative. CArrAdapter
MyBadArrAdapter(NULL, -3, -99);

6. MyBadArrAdapter(-4, -123);//Your if condition would not pick this
up, and would not throw

7. I also find very little value in this class, since it does not do
any clean up work, and therefore you would most likely end up with
memory leaks. It would be just as bad as using raw pointers.

Anyone using this type of class in a real world requirement, would end
up with memory leaks, poor performance, and a maintenance nightmare.

Nov 29 '05 #43
ro**********@gmail.com wrote:
Gianni Mariani wrote:

... Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -


(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.

I can pretty much answer your entire post right here as this is the
main point. I have already stated that legacy code is an issue. There
is no nice way to deal with code that needs [][] especially if it was
written with C style arrays in mind. Your template classes look nice
but I believe your use of [][] was a mistake.


Stop.

You have 2 options, a) makes for hard work, b) means less work. The
result is identical from a performance prespective. You insist on
option a).

Enough said.
Nov 29 '05 #44

ro**********@gmail.com wrote:
Gianni Mariani wrote:
... Creating a proxy answers this problem by
returning an object that just stores X and calls (x,y) on the matrix to
return the appropriate value. This is totally unnecissary and only
adds to the complexity of the program without giving any real benefit -


(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.


I can pretty much answer your entire post right here as this is the
main point. I have already stated that legacy code is an issue. There
is no nice way to deal with code that needs [][] especially if it was
written with C style arrays in mind. Your template classes look nice
but I believe your use of [][] was a mistake.

Now, I have already stated that legacy code or orders from on high are
one thing, but designing a mistake like this in from scratch is a big
mistake. Your template class works great and is rather efficient for C
style array and with vectors of vectors. A C function will still of
course not be able to deal with vectors of vectors so if you have to
use one you are already up shit creek.

But lets look at it from a fresh view kind of standpoint. Being as we
can set asside the issue of legacy code that depends on C style arrays
we can evaluate each implementation's merrit without artificial
requirements. When we are designing from scratch we want robust code
that is also fast. Robust in that it verifys inputs and makes sure
that clients don't try to do something they shouldn't (the argument for
robust code is pretty well known and accepted so I won't go there). We
want fast in both development and testing time as well as run time;
this means we want to do as little as possible to get the job done.

We can create our general functions with the [][] syntax or () syntax -
or with a standard function for that matter. C arrays are obviously
better suited for the [][] syntax so it might seem like the best
choice. However, objects appear to be better suited for the () syntax
for reasons that have already been gone over several times -> The only
protected way to provide [][] in an object is to create an adapter for
the () or function call interface; we can create a simpler
implementation but we expose the internals of the class and basically
ruin the whole purpose of a class so that our array would be better
just exposed and used normally (the only reasons to create an object
class is because of the protections such constructs offer - otherwise
simple functions and PODs are much better).

So, someone already showed us some basics of what would be needed to
implement the () to [][] adapter for an object and still let the class
construct do its job; it was comparitively involved and it wasn't even
finished. So, how would you make an adapter for the other method? I
myself might provide something as simple as:

template<typename T>
class CArrAdapter
{
T * data;
int col_num;
int row_num;
public:
CArrAdapter(T * d, int c, int r) : data(d), col_num(c), row_num(r) {}
T operator () (int i, int j) { if ( i > row_num || j > col_num) throw
something; return *(data + i * col_num + j); }
};

That to me looks a lot simpler, smaller, easier to test and validate,
and just all around better than the adapter required to change () into
[][].


I forgot to mention that your wrapper class also fails to have a GetCol
and GetRow function.

For better advise on this subject, check out the following CodeGuru STL
FAQs:
http://www.codeguru.com/forum/showthread.php?t=231046

The above STL FAQ has a wrapper class for a 2D array, which uses
vector<vector<T> >.
It has a resize function that allows the size to change after object
construction.
It would be safer to use this type of implementation, and it would be
eaiser to interface your code with STL objects.

The CodeGuru FAQ author also originally promoted the operator() method,
and after much debate, he changed the FAQ to promote [][] instead.

The CodeGuru site is a well known respected site, that has members that
are much better at responding to critiques then the author of the C++
FAQ.

Also check out another CodeGuru STL FAQ:
http://www.codeguru.com/forum/showth...hreadid=297838

The above link has two classes. One which I'm the author of, and the
second class which allows you to use both [][] and operator() method.
I don't think it's a good idea to have both methods in a class, but
some developers may find this method more acceptable.

Nov 29 '05 #45
Axter wrote:
....
The above link has two classes. One which I'm the author of, and the
second class which allows you to use both [][] and operator() method.
I don't think it's a good idea to have both methods in a class, but
some developers may find this method more acceptable.


I thought about putting both () and [][] in a class and I came to the
conclusion that you don't want to encourage both methods. You really
only want one, if someone is desperate for a (x,y) method, they can
easily add one.
Nov 29 '05 #46
jrp
Are there any additional issues with extending this code to THREE
dimensions?

Nov 29 '05 #47
jrp wrote:
Are there any additional issues with extending this code to THREE
dimensions?


For dynamically sized matrix classes of three or more dimensions, if you
want to use a [][][] syntax, you need to use a proxy object as a result
of the first operator[] calls > 2.
Nov 30 '05 #48

Axter wrote:
However, objects appear to be better suited for the () syntax
for reasons that have already been gone over several times ->

I completely disagree. I've only read contrived justifications for
using () syntax, that have nothing to do with generic programming, or
with 99.99% of C++ development.
Example:
Previous Post:
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>
Tell me then, how exactly is the compiler going to hide the internal representiation of
the matrix when you have exposed it with the first [] operator??!!
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>


99.99% of developers would never ever need to get the internal
representation of the matrix, and would never need to change col for
row within the matrix.


Uh...the problem I have cited over and over and over again with all but
one implementation of the operator[][] method of matrix/2d array has
been that the internal rep is already exposed; there are a hundred
things wrong with this and I have reiterated some of these several
times. I don't know why you bring up the point that 99.99% of
developers don't need to access the internals of the matrix class...I
would make this a stronger point and say that 100% of developers do not
need to access the internals of a matrix class. Those that need more
performance than they can get through the interface should use a
different class or maybe they even need to use C arrays period and toss
out all the "OO Overhead".

You keep running around in circles missing the point completely. Now
you are just talking nonsense - well the statement you made makes
sense, just not in the context of the argument and certainly not
*against* anything I have said, in fact it only reinforces my points.

Nov 30 '05 #49

Gianni Mariani wrote:
jrp wrote:
Are there any additional issues with extending this code to THREE
dimensions?


For dynamically sized matrix classes of three or more dimensions, if you
want to use a [][][] syntax, you need to use a proxy object as a result
of the first operator[] calls > 2.


Why not just return &&array[x]

Notice how the () syntax keeps encapsulation without the need of an
adapter even with 2d and with 3d still doesn't need one.

Nov 30 '05 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: SimonC | last post by:
I'm looking to do something similar to a feature found on Ticketmaster.com, where you select your seats at a venue, and then you have two minutes in which to take or leave them. QUESTION 1a....
8
by: John Grenier | last post by:
Hi, I have to determine the "standing" (WIN - TIE - LOSS) from confrontations between two teams on a contest. The table matchResults has fields cont_id, team_id and contest_result (int). ...
6
by: Willem | last post by:
Hi, I have a newbie question: is it possible to make a search form in asp that searches in two different databases (access)? Willem
10
by: Hank1234 | last post by:
Can I use one Data Adapter and one Command Builder to update amny tables? Currently in my data adapter I query two tables and fill them into two tables in a data set. When I make a change to a...
6
by: Matt K. | last post by:
Hi there, I have a form in an Access project that contains a subform which displays the results of a query of the style "select * from where = #a certain date#". In the main part of the form...
7
by: Prabhudhas Peter | last post by:
I have two object instances of a same class... and i assigned values in both object instances (or the values can be taken from databse and assigned to the members of the objects)... Now i want to...
0
by: clintonG | last post by:
I applied aspnet_regsql to SQL2K which was working fine throughout Beta 2 development. After installing Visual Studio and SQL Express RTM my application has blown up. Logging in to the application...
9
by: Steven | last post by:
Hello, I have a question about strcmp(). I have four words, who need to be compared if it were two strings. I tried adding the comparison values like '(strcmp(w1, w2) + strcmp(w3, w4))', where...
9
by: dhable | last post by:
I just started working with Python and ran into an annoyance. Is there a way to avoid having to use the "from xxx import yyy" syntax from files in the same directory? I'm sure it's been asked a...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.