By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
432,069 Members | 1,716 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 432,069 IT Pros & Developers. It's quick & easy.

Two Dimensional Array Template

P: n/a
http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work correctly, does
anyone else know how to make a template for making two dimensional arrays from
std::vectors ??? I want to use normal Array[ROW][COL] Syntax.
Jan 1 '07 #1
Share this Question
Share on Google+
272 Replies


P: n/a
On 2007-01-02 00:03, Peter Olcott wrote:
http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work correctly, does
anyone else know how to make a template for making two dimensional arrays from
std::vectors ??? I want to use normal Array[ROW][COL] Syntax.
In the code posted (which you could have included):

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

The 'i_index * m_rows'-part seems kind of fishy to me. It's quite late
right now and I wont spend time thinking much about it, but I think that
'i_index / m_rows' would be more correct, but I might be wrong. Draw a
3x3 matrix on paper and do the math.

--
Erik Wikström
Jan 1 '07 #2

P: n/a

"Erik Wikström" <Er***********@telia.comwrote in message
news:hF*******************@newsb.telia.net...
On 2007-01-02 00:03, Peter Olcott wrote:
> http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work correctly, does
anyone else know how to make a template for making two dimensional arrays
from std::vectors ??? I want to use normal Array[ROW][COL] Syntax.

In the code posted (which you could have included):

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

The 'i_index * m_rows'-part seems kind of fishy to me. It's quite late right
now and I wont spend time thinking much about it, but I think that 'i_index /
m_rows' would be more correct, but I might be wrong. Draw a 3x3 matrix on
paper and do the math.

--
Erik Wikström
I had partially converted everything over to Array[ROW][COL] order. I discovered
that I needed to convert the above function to

return & ( m_data[ i_index * m_columns ] );

I discovered this solution to my problem within a minute after I posted this
message. The code that I had linked to may still be correct.

Thanks for your help.
Jan 2 '07 #3

P: n/a
"Peter Olcott" <No****@SeeScreen.comwrote:
http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work
correctly, does anyone else know how to make a template for making
two dimensional arrays from std::vectors ?
http://www.parashift.com/c++-faq-lit...html#faq-13.10
I want to use normal Array[ROW][COL] Syntax.
Why?
Jan 2 '07 #4

P: n/a

"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
"Peter Olcott" <No****@SeeScreen.comwrote:
> http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work
correctly, does anyone else know how to make a template for making
two dimensional arrays from std::vectors ?

http://www.parashift.com/c++-faq-lit...html#faq-13.10
>I want to use normal Array[ROW][COL] Syntax.

Why?
To eliminate the humongous learning curve cost of violating a universal
standard.
Jan 2 '07 #5

P: n/a
"Peter Olcott" <No****@SeeScreen.comwrote:
"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:
http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work
correctly, does anyone else know how to make a template for making
two dimensional arrays from std::vectors ?
http://www.parashift.com/c++-faq-lit...html#faq-13.10
I want to use normal Array[ROW][COL] Syntax.
Why?

To eliminate the humongous learning curve cost of violating a universal
standard.
Read the following two FAQs before making such a mistake.

http://www.parashift.com/c++-faq-lit...html#faq-13.11
http://www.parashift.com/c++-faq-lit...html#faq-13.12
Jan 2 '07 #6

P: n/a

"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
"Peter Olcott" <No****@SeeScreen.comwrote:
>"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:

http://groups.google.com/group/comp....092f0f6c9bf13a

I think that the operator[]() member function does not work
correctly, does anyone else know how to make a template for making
two dimensional arrays from std::vectors ?

http://www.parashift.com/c++-faq-lit...html#faq-13.10

I want to use normal Array[ROW][COL] Syntax.

Why?

To eliminate the humongous learning curve cost of violating a universal
standard.

Read the following two FAQs before making such a mistake.

http://www.parashift.com/c++-faq-lit...html#faq-13.11
http://www.parashift.com/c++-faq-lit...html#faq-13.12
For my purposes I like this one much better. It is very fast and uses the
standard interface.
I have tested this one, and it works consistently correctly.

// Dynamic Two-Dimensional Array Template
// Array2D.h 2007-01-01 3:02 PM
//
// comp.lang.c++ message from Gianni Mariani Nov 24, 2005 at 9:21 pm
// http://groups.google.com/group/comp....092f0f6c9bf13a
// The last three member functions were added by Peter Olcott .
// Other minor adaptations by Peter Olcott
//

#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <vector>

template <typename w_elem_type>
class Array2D
{
typedef unsigned int t_Size;

private:
t_Size m_rows;
t_Size m_columns;
std::vector<w_elem_type m_data;

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

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

t_Size height() { return m_rows; };
t_Size width() { return m_columns; };
void resize( t_Size i_rows, t_Size i_columns );
};

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

#endif
Jan 2 '07 #7

P: n/a
"Peter Olcott" <No****@SeeScreen.comwrote:
"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:
"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:

http://groups.google.com/group/comp.lang.c++/msg/
a9092f0f6c9bf13a
>
I think that the operator[]() member function does not work
correctly, does anyone else know how to make a template for
making two dimensional arrays from std::vectors ?

http://www.parashift.com/c++-faq-lit...or-overloading.
html#faq-13.10

I want to use normal Array[ROW][COL] Syntax.

Why?
>
To eliminate the humongous learning curve cost of violating a
universal standard.
Read the following two FAQs before making such a mistake.

http://www.parashift.com/c++-faq-lit...rloading.html#
faq-13.11
http://www.parashift.com/c++-faq-lit...rloading.html#
faq-13.12

For my purposes I like this one much better. It is very fast and
uses the standard interface. I have tested this one, and it works
consistently correctly.

// Dynamic Two-Dimensional Array Template
// Array2D.h 2007-01-01 3:02 PM
//
// comp.lang.c++ message from Gianni Mariani Nov 24, 2005 at 9:21 pm
// http://groups.google.com/group/comp....092f0f6c9bf13a
// The last three member functions were added by Peter Olcott .
// Other minor adaptations by Peter Olcott
//
WARNING: the code below will not work with a w_elem_type of bool
#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <vector>

template <typename w_elem_type>
class Array2D
{
typedef unsigned int t_Size;

private:
t_Size m_rows;
t_Size m_columns;
std::vector<w_elem_type m_data;

public:
The c_tor below should be made explicit.
Array2D( t_Size i_rows = 0, t_Size i_columns = 0 )
: m_rows( i_rows ),
m_columns( i_columns ),
m_data( i_rows * i_columns )
{}

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

t_Size height() { return m_rows; };
t_Size width() { return m_columns; };
void resize( t_Size i_rows, t_Size i_columns );
};

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

#endif
What happens when you decide you want to change your client code to use
a column major or sparse matrix? There goes your learning curve!

It would be better to have a single interface that can be used for row
major, column major, or sparse matrices. The users only need to learn
one interface, and you can change the implementation without modifying
the code that uses the class.

Really, read the FAQ on the subject.
Jan 2 '07 #8

P: n/a

Peter Olcott wrote:
For my purposes I like this one much better. It is very fast and uses the
standard interface.
There is nothing "standard" about [][].
I have tested this one, and it works consistently correctly.

// Dynamic Two-Dimensional Array Template
// Array2D.h 2007-01-01 3:02 PM
//
// comp.lang.c++ message from Gianni Mariani Nov 24, 2005 at 9:21 pm
// http://groups.google.com/group/comp....092f0f6c9bf13a
// The last three member functions were added by Peter Olcott .
// Other minor adaptations by Peter Olcott
//

#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <vector>

template <typename w_elem_type>
class Array2D
{
typedef unsigned int t_Size;

private:
t_Size m_rows;
t_Size m_columns;
std::vector<w_elem_type m_data;

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

w_elem_type* operator[]( t_Size i_index ) {
return & ( m_data[ i_index * m_columns ] );
}
You should at the least have a typedef for this return in order to
abstractify what you are returning. You don't need to know that you
are getting an elem_type* only that you can retrieve a reference to an
elem_type through [] on the returned data item.

There are numerous problems with the class as described but so long as
you stick to some rather narrowly defined requirements you should be
ok. Of course, letting too much code depend on it will only make
things harder to change later.

Lots of luck to you.

Jan 2 '07 #9

P: n/a
Daniel T. wrote:
....
>
Really, read the FAQ on the subject.
I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of
what you need. Admitedly, this particular implementation is a bit
sparse, but that is an asset too...

resize is also implemented incorrectly (IMHO), but that's a detail.
Jan 2 '07 #10

P: n/a
Hello again!

I don't know if you remember me, but I remember you.

Peter Olcott wrote:
"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
>"Peter Olcott" <No****@SeeScreen.comwrote:
[...]
>>I want to use normal Array[ROW][COL] Syntax.
Why?

To eliminate the humongous learning curve cost of violating a universal
standard.
That's just silly. First of all, "Array[ROW][COL]" is most certainly
*not* a "universal standard". (If you think different, please refer us
to the relevant standard. You know, something like ISO/IEC blah blah
blah.) Secondly, and more importantly, if you find the "learning curve"
of doing 'm(i, j)' "humongous" (?) compared to doing 'm[i][j]', then I'm
lost as to how you even managed to learn the 'm[i][j]' type stuff in the
first place. Anyway...

What I like to do is something like this:-

[Start C++ snippet here.]

template< typename T, typename Alloc = ::std::allocator<T
class matrix {

public:

// Types

typedef T value_type;
typedef Alloc allocator_type; // (Thank goodness for rebind!)

typedef /* something */ row_size_type; // Size of a row.
typedef /* something */ col_size_type; // Size of a column.
typedef /* something */ row_difference_type; /* Difference between
row sizes. */
typedef /* something */ col_difference_type; /* Difference between
col_sizes. */

typedef /* something */ reference;
typedef /* something */ const_reference;
typedef /* something */ pointer;
typedef /* something */ const_pointer;

typedef /* something */ row_reference; // Reference to row.
typedef /* something */ const_row_reference;
typedef /* something */ col_reference; // Reference to column.
typedef /* something */ const_col_reference;
typedef /* something */ row_pointer; // Pointer to row.
typedef /* something */ const_row_pointer;
typedef /* something */ col_pointer; // Pointer to column.
typedef /* something */ const_col_pointer;

/* Note that the above reference and pointer types do not have to be
of the form 'sometype &' or 'sometype *'. They just need to be
types that can be used as references and pointers.
*/

typedef /* something */ row_iterator; /* Iterator over rows,
not over the elements
of a row. */
typedef /* something */ const_row_iterator;
typedef /* something */ col_iterator; // Iterator over columns.
typedef /* something */ const_col_iterator;
typedef /* something */ reverse_row_iterator;
typedef /* something */ const_reverse_row_iterator;
typedef /* something */ reverse_col_iterator;
typedef /* something */ const_reverse_col_iterator;

// Row, Column and Element Access

reference operator() (col_size_type i, row_size_type j);
/* Returns a reference to the element in row (not column) i and
column j. */
const_reference operator() (col_size_type i, row_size_type j) const;

row_reference row (col_size_type i);
// Returns a reference to row i.
const_row_reference row (col_size_type i) const;
col_reference col (row_size_type j);
const_col_reference col (row_size_type j) const;

row_reference operator[] (col_size_type i) { return row(i); }
const_row_reference operator[] (col_size_type i) const {
return row(i);
}
/* As long as row_references are subscriptable, the familiar (to C
programmers) 'm[i][j]' style subscripting can be done. With
suitable inlining, such subscripting can be optimized (by the
compiler) into something more efficient. And things like 'm[i]'
can be used to get one-dimensional-array-like references and things
to be passed around to code that operates on
one-dimensional-array-like things.

But row() and col() are clearer, more explicit, than things like
'm[i][j]' (though my naming of the size and difference types could
be confusing!). Clarity is a good thing. And, as long as
row_references and col_references (and their const versions) have
their own col() and row() member functions, we can write code such
as 'm.row(i).col(j)' - very clear! And, again, with suitable
inlining, we can have it optimized away to something more
efficient.
*/

// Iterators

row_iterator row_begin ();
const_row_iterator const_row_begin ();
row_iterator row_end ();
const_row_iterator const_row_end ();
col_iterator col_begin ();
const_col_iterator const_col_begin ();
col_iterator col_end ();
const_col_iterator const_col_end ();

// (And similarly for reverse iterators.)

// ...
};

[End C++ snippet here.]

Ah, but how's it implemented? Well, I was focussing on the interface,
as that seems to be what you're bothered about. More importantly, the
interface /should not/ be dictated by the implementation. Neither is it
desirable to have the implementation needlessly restricted by the
interface. That's why there are all those "/* something */"s. They
don't necessarily all have to be typedefs, either. Basically, the idea
is to provide an interface that's consistent with the /concept/ of a
matrix, while keeping the /implementation/ behind the scenes.

As long as the interface is sufficiently independent of the
implementation, and the implementation's not needlessly restricted by
the interface, you should be able to have an interface that's clear and
reasonably intuitive to use, at the same time as having an
implementation that does the job well.

:-)

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #11

P: n/a
Gianni Mariani wrote:
Daniel T. wrote:
...
>>
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.
When I read the first FAQ mentioned, I, too, thought it wrong. But then
I read the second FAQ (which followed immediately after). That second
FAQ is not so disagreeable.

I think the real issue is proper separation of interface and implementation.

:-)

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #12

P: n/a
On 2007-01-02 12:55, Gianni Mariani wrote:
Daniel T. wrote:
...
>>
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of
what you need.
And your error is to assume that only a simple 2D array will ever be needed.
Admitedly, this particular implementation is a bit
sparse, but that is an asset too...
What do you mean that it's sparse? The way I see it it's as dense as any
implementation I've ever seen.

--
Erik Wikström
Jan 2 '07 #13

P: n/a
Erik Wikström wrote:
On 2007-01-02 12:55, Gianni Mariani wrote:
....
Admitedly, this particular implementation is a bit
sparse, but that is an asset too...

What do you mean that it's sparse? The way I see it it's as dense as any
implementation I've ever seen.
I think he meant there's not much to the implementation, rather than it
being for sparse matrices.

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #14

P: n/a
Gianni Mariani <gi*******@mariani.wswrote:
Daniel T. wrote:
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with
the assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of
what you need. Admitedly, this particular implementation is a bit
sparse, but that is an asset too...
However, the OPs complaint has to do with the "humongous learning
curve". Requiring a different interface for row major, column major, and
sparse matrices, as well as a different interface for boolean matrices
as opposed to int matrices is much harder on the user.
resize is also implemented incorrectly (IMHO), but that's a detail.
Also, the class doesn't work for bool matrices.
Jan 2 '07 #15

P: n/a

Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
Daniel T. wrote:
Really, read the FAQ on the subject.
I did read the FAQ on the subject a while ago and I disagree with
the assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of
what you need. Admitedly, this particular implementation is a bit
sparse, but that is an asset too...

However, the OPs complaint has to do with the "humongous learning
curve". Requiring a different interface for row major, column major, and
sparse matrices, as well as a different interface for boolean matrices
as opposed to int matrices is much harder on the user.
The OP didn't mention matrices at all. Admitedly a 2d array is pretty
much the same thing but the two titles have slightly different
meanings. A "matrix" is usually used in some linear algebra
calculations or other mathematical implementation....a 2d array is more
general. A matrix can be abstracted to hold any interface and so there
is no reason to use [][] over something else. A "2d array" isn't so
abstract so if you want a "2d array" class then you're pretty much
stuck doing something stupid and/or complex since the sole object of
such a class is to look like a 2d array. I think this is what the OP
is refering to, not what you are saying.

Why you should wrap a 2d array into a class that offers no abstractions
of course is a question. Seems to me there is usually a more
appropriate abstraction for the needs of the domain, and using the
basic data types much easier otherwise, but I don't usually take any
information not provided in my replies. Besides, this has all been
discussed to death and no ground made. If someone really feels they
need to do this to themselves, let them.

Jan 2 '07 #16

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
Daniel T. wrote:
...
>>
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of what you
need. Admitedly, this particular implementation is a bit sparse, but that is
an asset too...

resize is also implemented incorrectly (IMHO), but that's a detail.
How would you improve how resize() is implemented?
Jan 2 '07 #17

P: n/a

"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@v33g2000cwv.googlegr oups.com...
>
Peter Olcott wrote:
>For my purposes I like this one much better. It is very fast and uses the
standard interface.

There is nothing "standard" about [][].
>I have tested this one, and it works consistently correctly.

// Dynamic Two-Dimensional Array Template
// Array2D.h 2007-01-01 3:02 PM
//
// comp.lang.c++ message from Gianni Mariani Nov 24, 2005 at 9:21 pm
// http://groups.google.com/group/comp....092f0f6c9bf13a
// The last three member functions were added by Peter Olcott .
// Other minor adaptations by Peter Olcott
//

#ifndef ARRAY2D_H
#define ARRAY2D_H
#include <vector>

template <typename w_elem_type>
class Array2D
{
typedef unsigned int t_Size;

private:
t_Size m_rows;
t_Size m_columns;
std::vector<w_elem_type m_data;

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

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

You should at the least have a typedef for this return in order to
abstractify what you are returning. You don't need to know that you
are getting an elem_type* only that you can retrieve a reference to an
elem_type through [] on the returned data item.
I have no idea what you are talking about. You get a pointer to whatever type
formed the parameter to the template. Why is this not perfect the way that it
is?
There are numerous problems with the class as described but so long as
you stick to some rather narrowly defined requirements you should be
ok. Of course, letting too much code depend on it will only make
things harder to change later.
This class should provide a two dimensional array of anything, what
imperfections do you see with this?
>
Lots of luck to you.

Jan 2 '07 #18

P: n/a

"Simon G Best" <si**********@btinternet.comwrote in message
news:b8******************************@bt.com...
Hello again!

I don't know if you remember me, but I remember you.

Peter Olcott wrote:
>"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.ear thlink.net...
>>"Peter Olcott" <No****@SeeScreen.comwrote:
[...]
>>>I want to use normal Array[ROW][COL] Syntax.
Why?

To eliminate the humongous learning curve cost of violating a universal
standard.

That's just silly. First of all, "Array[ROW][COL]" is most certainly *not* a
"universal standard". (If you think different, please refer us
This is the way that C/C++ are defined to work, it is a universal standard
within these two (and several other) languages.
to the relevant standard. You know, something like ISO/IEC blah blah blah.)
Secondly, and more importantly, if you find the "learning curve" of doing
'm(i, j)' "humongous" (?) compared to doing 'm[i][j]', then I'm lost as to how
you even managed to learn the 'm[i][j]' type stuff in the first place.
Anyway...

What I like to do is something like this:-

[Start C++ snippet here.]

template< typename T, typename Alloc = ::std::allocator<T
class matrix {

public:

// Types

typedef T value_type;
typedef Alloc allocator_type; // (Thank goodness for rebind!)

typedef /* something */ row_size_type; // Size of a row.
typedef /* something */ col_size_type; // Size of a column.
typedef /* something */ row_difference_type; /* Difference between
row sizes. */
typedef /* something */ col_difference_type; /* Difference between
col_sizes. */

typedef /* something */ reference;
typedef /* something */ const_reference;
typedef /* something */ pointer;
typedef /* something */ const_pointer;

typedef /* something */ row_reference; // Reference to row.
typedef /* something */ const_row_reference;
typedef /* something */ col_reference; // Reference to column.
typedef /* something */ const_col_reference;
typedef /* something */ row_pointer; // Pointer to row.
typedef /* something */ const_row_pointer;
typedef /* something */ col_pointer; // Pointer to column.
typedef /* something */ const_col_pointer;

/* Note that the above reference and pointer types do not have to be
of the form 'sometype &' or 'sometype *'. They just need to be
types that can be used as references and pointers.
*/

typedef /* something */ row_iterator; /* Iterator over rows,
not over the elements
of a row. */
typedef /* something */ const_row_iterator;
typedef /* something */ col_iterator; // Iterator over columns.
typedef /* something */ const_col_iterator;
typedef /* something */ reverse_row_iterator;
typedef /* something */ const_reverse_row_iterator;
typedef /* something */ reverse_col_iterator;
typedef /* something */ const_reverse_col_iterator;

// Row, Column and Element Access

reference operator() (col_size_type i, row_size_type j);
/* Returns a reference to the element in row (not column) i and
column j. */
const_reference operator() (col_size_type i, row_size_type j) const;

row_reference row (col_size_type i);
// Returns a reference to row i.
const_row_reference row (col_size_type i) const;
col_reference col (row_size_type j);
const_col_reference col (row_size_type j) const;

row_reference operator[] (col_size_type i) { return row(i); }
const_row_reference operator[] (col_size_type i) const {
return row(i);
}
/* As long as row_references are subscriptable, the familiar (to C
programmers) 'm[i][j]' style subscripting can be done. With
suitable inlining, such subscripting can be optimized (by the
compiler) into something more efficient. And things like 'm[i]'
can be used to get one-dimensional-array-like references and things
to be passed around to code that operates on
one-dimensional-array-like things.

But row() and col() are clearer, more explicit, than things like
'm[i][j]' (though my naming of the size and difference types could
be confusing!). Clarity is a good thing. And, as long as
row_references and col_references (and their const versions) have
their own col() and row() member functions, we can write code such
as 'm.row(i).col(j)' - very clear! And, again, with suitable
inlining, we can have it optimized away to something more
efficient.
*/

// Iterators

row_iterator row_begin ();
const_row_iterator const_row_begin ();
row_iterator row_end ();
const_row_iterator const_row_end ();
col_iterator col_begin ();
const_col_iterator const_col_begin ();
col_iterator col_end ();
const_col_iterator const_col_end ();

// (And similarly for reverse iterators.)

// ...
};

[End C++ snippet here.]

Ah, but how's it implemented? Well, I was focussing on the interface, as that
seems to be what you're bothered about. More importantly, the interface
/should not/ be dictated by the implementation. Neither is it desirable to
have the implementation needlessly restricted by the interface. That's why
there are all those "/* something */"s. They don't necessarily all have to be
typedefs, either. Basically, the idea is to provide an interface that's
consistent with the /concept/ of a matrix, while keeping the /implementation/
behind the scenes.

As long as the interface is sufficiently independent of the implementation,
and the implementation's not needlessly restricted by the interface, you
should be able to have an interface that's clear and reasonably intuitive to
use, at the same time as having an implementation that does the job well.

:-)

Simon

--
What happens if I mention Leader Kibo in my .signature?

Jan 2 '07 #19

P: n/a

"Erik Wikström" <Er***********@telia.comwrote in message
news:Q%*******************@newsb.telia.net...
On 2007-01-02 12:55, Gianni Mariani wrote:
>Daniel T. wrote:
...
>>>
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of what you
need.

And your error is to assume that only a simple 2D array will ever be needed.
That is the specified scope of the problem, within this specified scope, the
solution (as far as I can tell) is perfect. If one does not restrict oneself to
the specified scope, then any possible solution to any possible problem becomes
totally lacking and woefully inadequate simply because the solution does not
solve EVERY POSSIBLE problem.
>
Admitedly, this particular implementation is a bit
sparse, but that is an asset too...

What do you mean that it's sparse? The way I see it it's as dense as any
implementation I've ever seen.

--
Erik Wikström

Jan 2 '07 #20

P: n/a

Peter Olcott wrote:
"Noah Roberts" <ro**********@gmail.comwrote in message
news:11**********************@v33g2000cwv.googlegr oups.com...

Peter Olcott wrote
w_elem_type* operator[]( t_Size i_index ) {
return & ( m_data[ i_index * m_columns ] );
}
You should at the least have a typedef for this return in order to
abstractify what you are returning. You don't need to know that you
are getting an elem_type* only that you can retrieve a reference to an
elem_type through [] on the returned data item.

I have no idea what you are talking about. You get a pointer to whatever type
formed the parameter to the template. Why is this not perfect the way that it
is?
I'll answer that question by asking another....why do you think
std::vector (for example, all of them do) has a "reference_type"
typedef embedded in the class and returns that instead of value_type&
even though they are quite often the same thing?

Jan 2 '07 #21

P: n/a
Peter Olcott wrote:
"Simon G Best" <si**********@btinternet.comwrote in message
news:b8******************************@bt.com...
....
>That's just silly. First of all, "Array[ROW][COL]" is most certainly *not* a
"universal standard". (If you think different, please refer us

This is the way that C/C++ are defined to work, it is a universal standard
within these two (and several other) languages.
C, maybe, but not C++. *C++ is not C.* Certainly C++ has C-style
arrays, but C++ *does not* constrain or require you to give your own
array classes that C-style kind of interface. So, no, it simply isn't
true that C++ is "defined to work" that way.

(I'm also wondering why you call it a "universal standard" when it's
only /some/ languages that do it that way. In what way is it
"universal"? What do you mean by "universal standard within these ...
languages"?)

Anyway, the idea with C++ is that you generally *don't* do things in
C-style ways. As is so often said, *C++ is not C.* Yes, C++ has
inherited C-style arrays, but you're generally not supposed to use them,
or do things in that style. (If you want to do things that way, there's
already a perfectly good language for it - C.) Instead, you're supposed
to use safer classes, with suitable interfaces. That includes using
operator() for subscripting when that's what's appropriate.

But let me ask you a question. If you use C-style subscripting, with
operator[], to access a whole row, then what do you use to access a
whole column?

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #22

P: n/a
"Peter Olcott" <No****@SeeScreen.comwrote:
"Erik Wikström" <Er***********@telia.comwrote:
On 2007-01-02 12:55, Gianni Mariani wrote:
Daniel T. wrote: ...

Really, read the FAQ on the subject.
>
I did read the FAQ on the subject a while ago and I disagree
with the assertions. IMHO, the FAQ has this one dead wrong.
>
If all you need is a simple 2D array, then this one provides
most of what you need.
And your error is to assume that only a simple 2D array will ever
be needed.

That is the specified scope of the problem, within this specified
scope, the solution (as far as I can tell) is perfect.
"Simple 2D array" should be able to handle a 2D array of booleans, but
your class cannot. There is nothing in the definition of "simple 2D
array" that requires a particular memory layout, yet your interface
makes such a requirement.

These are just two ways in which your class is more restrictive than the
specified scope of the problem. Unless you want to change the
specification to "2D array of things other than bools in row major form
with each row laid out in contiguous RAM."
Jan 2 '07 #23

P: n/a

"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
"Peter Olcott" <No****@SeeScreen.comwrote:
>"Erik Wikström" <Er***********@telia.comwrote:
On 2007-01-02 12:55, Gianni Mariani wrote:
Daniel T. wrote: ...

Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree
with the assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides
most of what you need.

And your error is to assume that only a simple 2D array will ever
be needed.

That is the specified scope of the problem, within this specified
scope, the solution (as far as I can tell) is perfect.

"Simple 2D array" should be able to handle a 2D array of booleans, but
your class cannot. There is nothing in the definition of "simple 2D
array" that requires a particular memory layout, yet your interface
makes such a requirement.

These are just two ways in which your class is more restrictive than the
specified scope of the problem. Unless you want to change the
specification to "2D array of things other than bools in row major form
with each row laid out in contiguous RAM."
Yes, the same as the native code definition, they both seem to work fine with
bool, too.
Jan 2 '07 #24

P: n/a
Peter Olcott wrote:
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
>Daniel T. wrote:
...
>>Really, read the FAQ on the subject.
I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of what you
need. Admitedly, this particular implementation is a bit sparse, but that is
an asset too...

resize is also implemented incorrectly (IMHO), but that's a detail.

How would you improve how resize() is implemented?
Resize should (IMHO) preserve the rows/columns as far as possible

3x3 array
A B C
D E F
G H I

when resized should do:

resize to 2x2 array
A B
D E

resize to 4x4
A B C 0
D E F 0
G H I 0
0 0 0 0

The resize implementation in a previous post does:

resize to 2x2
A B
C D

resize to 4x4
A B C D
E F G H
I 0 0 0
0 0 0 0

Anyhow, if the resize implementation you have works for you, then don't
listen to me. Personally, I wouldn't even provide one until I needed one
since it looks like we're going for the minimal solution anyway.

Also, to placate Daniel T, I would specialize Array2D<boollike so:

template <>
class Array2D<bool>;

.... and then fill in the blanks whenever you need Array2D<bool>, if ever.
Jan 2 '07 #25

P: n/a
"Peter Olcott" <No****@SeeScreen.comwrote:
"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:
That is the specified scope of the problem, within this specified
scope, the solution (as far as I can tell) is perfect.
"Simple 2D array" should be able to handle a 2D array of booleans, but
your class cannot. There is nothing in the definition of "simple 2D
array" that requires a particular memory layout, yet your interface
makes such a requirement.

These are just two ways in which your class is more restrictive than the
specified scope of the problem. Unless you want to change the
specification to "2D array of things other than bools in row major form
with each row laid out in contiguous RAM."

Yes, the same as the native code definition,
There is no "native code definition" for 2D arrays. I believe the
standard makes no mention of multi-dimensional arrays at all. (Can
someone back me up on this?)

As the FAQ posits: "Now everybody knows that you are different. You are
clairvoiant with perfect knowledge of the future..." Somehow, you just
know that nobody who uses your class will want to switch to a sparse
array or a column major array. Or maybe you just want to punish them if
they do want to make such a change, because your code will force them to
change every line that uses your class. If you were willing to be more
reasonable, then your users could change out 2DArrays without having to
chanage anything but the point of construction.
they both seem to work fine with bool, too.
The code you posted doesn't work fine with bool.

Assuming a standards conforming compiler, when w_elem_type is a bool,
the op[] function doesn't compile. If your op[] is compiling when
w_elem_type is a bool, your compiler is not standards conforming (or you
are not using the code you posted.)

The reason this is the case is because vector<bool::operator[] doesn't
return a bool& as your code assumes. You are taking the address of a
temporary and that is simply not allowed.
Jan 2 '07 #26

P: n/a
Simon G Best wrote:
Gianni Mariani wrote:
>Daniel T. wrote:
...
>>>
Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

When I read the first FAQ mentioned, I, too, thought it wrong. But then
I read the second FAQ (which followed immediately after). That second
FAQ is not so disagreeable.
OK, so it appears to have changed to what I read a while ago.
Unfortunately the change does not address the issue I raised and why (,)
syntax is not appropriate.

Firstly, the [][] syntax is directly equivalent to the (,) syntax as has
been shown in many prior posts. At this point, much of the impetus
behind the stance of the FAQ is gone.

The biggest reason I stick to [][] is that this IS the native syntax of
the language and hence array[][] (native) or Array2D class will work
almost interchangeably allowing for templates that are appropriate.
>
I think the real issue is proper separation of interface and
implementation.
If "interface separation" is an issue, implement a proxy class. The OP
does not seem to have any need for "interface separation".

I believe this next issue is done to death. This is often rebutted that
a proxy class will significantly detrimentally affect. Do the
benchmark, I think you'll find there is NO difference in performance
between the two approaches. Compilers today do an excellent job of
optimization such that there is no significant difference.

It's purely a syntax issue.

One side of the argument is: "this syntax is better", and the other is:
"don't invent new syntax where none is needed".

I think it's a no brainer personally. Go figure.
Jan 2 '07 #27

P: n/a

"Daniel T." <da******@earthlink.netwrote in message
news:da****************************@news.west.eart hlink.net...
"Peter Olcott" <No****@SeeScreen.comwrote:
>"Daniel T." <da******@earthlink.netwrote:
"Peter Olcott" <No****@SeeScreen.comwrote:

That is the specified scope of the problem, within this specified
scope, the solution (as far as I can tell) is perfect.

"Simple 2D array" should be able to handle a 2D array of booleans, but
your class cannot. There is nothing in the definition of "simple 2D
array" that requires a particular memory layout, yet your interface
makes such a requirement.

These are just two ways in which your class is more restrictive than the
specified scope of the problem. Unless you want to change the
specification to "2D array of things other than bools in row major form
with each row laid out in contiguous RAM."

Yes, the same as the native code definition,

There is no "native code definition" for 2D arrays. I believe the
standard makes no mention of multi-dimensional arrays at all. (Can
someone back me up on this?)

As the FAQ posits: "Now everybody knows that you are different. You are
clairvoiant with perfect knowledge of the future..." Somehow, you just
know that nobody who uses your class will want to switch to a sparse
array or a column major array. Or maybe you just want to punish them if
they do want to make such a change, because your code will force them to
change every line that uses your class. If you were willing to be more
reasonable, then your users could change out 2DArrays without having to
chanage anything but the point of construction.
>they both seem to work fine with bool, too.

The code you posted doesn't work fine with bool.

Assuming a standards conforming compiler, when w_elem_type is a bool,
the op[] function doesn't compile. If your op[] is compiling when
w_elem_type is a bool, your compiler is not standards conforming (or you
are not using the code you posted.)
So what exactly is this issue with this is the official standard for bool, to
make sure no official standard exists? Just make the official standard that a
bool is always implemented as some consistent thing such as char, and with some
consistent value such as one for true, and zero for false. Why did anyone ever
make it more complicated than this?
>
The reason this is the case is because vector<bool::operator[] doesn't
return a bool& as your code assumes. You are taking the address of a
temporary and that is simply not allowed.

Jan 2 '07 #28

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
Simon G Best wrote:
>Gianni Mariani wrote:
>>Daniel T. wrote:
...

Really, read the FAQ on the subject.

I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

When I read the first FAQ mentioned, I, too, thought it wrong. But then I
read the second FAQ (which followed immediately after). That second FAQ is
not so disagreeable.

OK, so it appears to have changed to what I read a while ago. Unfortunately
the change does not address the issue I raised and why (,) syntax is not
appropriate.

Firstly, the [][] syntax is directly equivalent to the (,) syntax as has been
shown in many prior posts. At this point, much of the impetus behind the
stance of the FAQ is gone.

The biggest reason I stick to [][] is that this IS the native syntax of the
language and hence array[][] (native) or Array2D class will work almost
interchangeably allowing for templates that are appropriate.
>>
I think the real issue is proper separation of interface and implementation.

If "interface separation" is an issue, implement a proxy class. The OP does
not seem to have any need for "interface separation".

I believe this next issue is done to death. This is often rebutted that a
proxy class will significantly detrimentally affect. Do the benchmark, I
think you'll find there is NO difference in performance between the two
approaches. Compilers today do an excellent job of optimization such that
there is no significant difference.

It's purely a syntax issue.

One side of the argument is: "this syntax is better", and the other is: "don't
invent new syntax where none is needed".

I think it's a no brainer personally. Go figure.
I still like yours the best. I made sure to give you credit in my source code.
Jan 2 '07 #29

P: n/a
Peter Olcott wrote:
....
>
So what exactly is this issue with this is the official standard for bool, to
make sure no official standard exists?
vector<boolis specialized. It stores bits not bools. the [] operator
on a vector<boolproduces a proxy class that will perform the correct
bitwise operations to set/clear the bits.
Jan 2 '07 #30

P: n/a

"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
Peter Olcott wrote:
>"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
>>Daniel T. wrote:
...
Really, read the FAQ on the subject.
I did read the FAQ on the subject a while ago and I disagree with the
assertions. IMHO, the FAQ has this one dead wrong.

If all you need is a simple 2D array, then this one provides most of what
you need. Admitedly, this particular implementation is a bit sparse, but
that is an asset too...

resize is also implemented incorrectly (IMHO), but that's a detail.

How would you improve how resize() is implemented?

Resize should (IMHO) preserve the rows/columns as far as possible

3x3 array
A B C
D E F
G H I

when resized should do:

resize to 2x2 array
A B
D E

resize to 4x4
A B C 0
D E F 0
G H I 0
0 0 0 0

The resize implementation in a previous post does:

resize to 2x2
A B
C D

resize to 4x4
A B C D
E F G H
I 0 0 0
0 0 0 0

Anyhow, if the resize implementation you have works for you, then don't listen
to me. Personally, I wouldn't even provide one until I needed one since it
looks like we're going for the minimal solution anyway.
My main reason for needing this template class was to support searching the
screen using my patented DFA recognizer:
www.SeeScreen.com
I built a screen capture that captures the screen to Array2D Screen; Now each
pixel of (a copy of) the screen can be quickly accessed.
>
Also, to placate Daniel T, I would specialize Array2D<boollike so:

template <>
class Array2D<bool>;

... and then fill in the blanks whenever you need Array2D<bool>, if ever.

Jan 2 '07 #31

P: n/a
Gianni Mariani wrote:
....
If "interface separation" is an issue, implement a proxy class. The OP
does not seem to have any need for "interface separation".
I do like proxy classes :-)
I believe this next issue is done to death. This is often rebutted that
a proxy class will significantly detrimentally affect. Do the
benchmark, I think you'll find there is NO difference in performance
between the two approaches. Compilers today do an excellent job of
optimization such that there is no significant difference.
And I especially like proxy classes when they're done right, so that
things get inlined and optimized all the way down :-)

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #32

P: n/a
Gianni Mariani <gi*******@mariani.wswrote:
Also, to placate Daniel T, I would specialize Array2D<boollike so:

template <>
class Array2D<bool>;

... and then fill in the blanks whenever you need Array2D<bool>, if ever.
Can that be done? The code posted assumes that any portion of the vector
can be converted into an array of pointers. How would you change the
implementation when that is not the case? Once you come up with the
change, why does the primary implementation use something different?

(BTW, I'm not being rhetorical with these questions. I really want to
know the answer.)
Jan 2 '07 #33

P: n/a
Peter Olcott wrote:
So what exactly is this issue with this is the official standard for bool,
to make sure no official standard exists? Just make the official standard
that a bool is always implemented as some consistent thing such as char,
and with some consistent value such as one for true, and zero for false.
Just change the standard to avoid that you have to learn and think.

--
Salu2
Jan 2 '07 #34

P: n/a
Peter Olcott wrote:
>
So what exactly is this issue with this is the official standard for bool, to
make sure no official standard exists?
Uh?
Just make the official standard that a
bool is always implemented as some consistent thing such as char, and with some
consistent value such as one for true, and zero for false. Why did anyone ever
make it more complicated than this?
It's so that space can be saved. A bool can be represented by a single
bit, but the smallest addressable unit of storage is a char - at least
eight bits. So, it's either one bool per char (wastes space), or
internally representing the bools in such a way that they can't be
individually referenced using built-in reference types (such as char &
or bool &). So that space need not be wasted, the standard has
std::vector<boolspecialized so that built-in reference types aren't
used. This means as many bools can be stored in a char (or whatever) as
possible, saving space.

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #35

P: n/a

Simon G Best wrote:
Peter Olcott wrote:

So what exactly is this issue with this is the official standard for bool, to
make sure no official standard exists?

Uh?
Just make the official standard that a
bool is always implemented as some consistent thing such as char, and with some
consistent value such as one for true, and zero for false. Why did anyone ever
make it more complicated than this?

It's so that space can be saved. A bool can be represented by a single
bit, but the smallest addressable unit of storage is a char - at least
eight bits. So, it's either one bool per char (wastes space), or
internally representing the bools in such a way that they can't be
individually referenced using built-in reference types (such as char &
or bool &). So that space need not be wasted, the standard has
std::vector<boolspecialized so that built-in reference types aren't
used. This means as many bools can be stored in a char (or whatever) as
possible, saving space.
At a pretty significant cost though. vector<boolis not a container.
It kind of throws the whole thing off. Better to use bitset instead.

Jan 2 '07 #36

P: n/a
Peter Olcott wrote:
>
My main reason for needing this template class was to support searching the
screen using my patented DFA recognizer:
www.SeeScreen.com
Oh, no. You're an inventor with a software patent :-(

Simon

--
What happens if I mention Leader Kibo in my .signature?
Jan 2 '07 #37

P: n/a
Gianni Mariani <gi*******@mariani.wswrote:
Simon G Best wrote:
Gianni Mariani wrote:
Daniel T. wrote: ...

Really, read the FAQ on the subject.
>
I did read the FAQ on the subject a while ago and I disagree
with the assertions. IMHO, the FAQ has this one dead wrong.
When I read the first FAQ mentioned, I, too, thought it wrong. But
then I read the second FAQ (which followed immediately after).
That second FAQ is not so disagreeable.

OK, so it appears to have changed to what I read a while ago.
Unfortunately the change does not address the issue I raised and why
(,) syntax is not appropriate.
Don't get so hung up on syntax.
Firstly, the [][] syntax is directly equivalent to the (,) syntax as
has been shown in many prior posts.
Actually it isn't. If it were, then I wouldn't bother suggesting to use
it over [][]. The (,) syntax is much more flexable than the [][] syntax.
It allows users to make more drastic changes to the way their code is
implemented with fewer changes to the actual text of the code.
The biggest reason I stick to [][] is that this IS the native syntax
of the language and hence array[][] (native) or Array2D class will
work almost interchangeably allowing for templates that are
appropriate.
As the FAQ mentions, if you "find yourself maintaining a billion-line
app where the original team used m[i][j]" things are different, but that
isn't a justification for starting a new project or library with such a
construct. Especially considering that more flexible constructs are
available that are "never worse than, and sometimes better than, the
[][] approach."
It's purely a syntax issue.
As mentioned in the FAQ, "there are easy performance tuning tricks that
can be done with the operator() approach that are more difficult in the
[][] approach." This is not merely a syntax issue.
One side of the argument is: "this syntax is better", and the other
is: "don't invent new syntax where none is needed".
No, one side of the argument is; don't box yourself in before the
project has really gotten started by exposing an implementation detail
that may not even be approprate.

On the other side is your argumentum ad antiquitatem fallacy. As the FAQ
says, "The world already has way too many exposed data structures and
way too many out-of-bounds parameters, and those cost way too much money
and cause way too many delays and way too many defects."
I think it's a no brainer personally. Go figure.
Now there, I can agree with you.
Jan 2 '07 #38

P: n/a
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
>Also, to placate Daniel T, I would specialize Array2D<boollike so:

template <>
class Array2D<bool>;

... and then fill in the blanks whenever you need Array2D<bool>, if ever.

Can that be done? The code posted assumes that any portion of the vector
can be converted into an array of pointers. How would you change the
implementation when that is not the case?
Apart from vector<bool>, this IS the C++ standard for std::vector. As
for Array2D<T>, I suppose you can return a proxy that gens a
std::vector<T>::reference_type instead of a pointer and there would be
no need to specialize Array2D. Still, if you don't need a <bool>
implementation, let's not make the OP worry about it.
... Once you come up with the
change, why does the primary implementation use something different?
I would not necessarily do anything different.
Jan 2 '07 #39

P: n/a
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
>Simon G Best wrote:
>>Gianni Mariani wrote:
Daniel T. wrote: ...
Really, read the FAQ on the subject.
I did read the FAQ on the subject a while ago and I disagree
with the assertions. IMHO, the FAQ has this one dead wrong.
When I read the first FAQ mentioned, I, too, thought it wrong. But
then I read the second FAQ (which followed immediately after).
That second FAQ is not so disagreeable.
OK, so it appears to have changed to what I read a while ago.
Unfortunately the change does not address the issue I raised and why
(,) syntax is not appropriate.

Don't get so hung up on syntax.
>Firstly, the [][] syntax is directly equivalent to the (,) syntax as
has been shown in many prior posts.

Actually it isn't.
I can show an implementation of [][] that calls call your (,) and most
compilers will optimize it so there is nothing different between calling
(,) or [][].

No issue with flexibility with optimizations here since it is calling
your (,) ! right ?

The FAQ is guilty of being a proponent of inventing a new syntax where
none in needed IMHO.

Now, if I create a bunch o 2D array templates, they will work fine with
both the new Array2D or a native 2D array. Do that with the (,) syntax!
It's just easier all the way around.
Jan 2 '07 #40

P: n/a

Gianni Mariani wrote:
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
Also, to placate Daniel T, I would specialize Array2D<boollike so:

template <>
class Array2D<bool>;

... and then fill in the blanks whenever you need Array2D<bool>, if ever.
Can that be done? The code posted assumes that any portion of the vector
can be converted into an array of pointers. How would you change the
implementation when that is not the case?

Apart from vector<bool>, this IS the C++ standard for std::vector. As
for Array2D<T>, I suppose you can return a proxy that gens a
std::vector<T>::reference_type instead of a pointer and there would be
no need to specialize Array2D. Still, if you don't need a <bool>
implementation, let's not make the OP worry about it.
Frankly I don't think vector<boolshould exist, at least not any
differently than any other type of vector. It throws a wrench into the
whole works and makes it impossible to create a real vector<bool>.

Jan 2 '07 #41

P: n/a
Gianni Mariani <gi*******@mariani.wswrote:
I can show an implementation of [][] that calls call your (,) and most
compilers will optimize it so there is nothing different between calling
(,) or [][].
By all means, do so. Really, I'm interested in seeing it. If you can
show one that still uses the interface shown by Peter, I'll be very
surprised.
The FAQ is guilty of being a proponent of inventing a new syntax where
none in needed IMHO.

Now, if I create a bunch o 2D array templates, they will work fine with
both the new Array2D or a native 2D array. Do that with the (,) syntax!
I don't believe there is a "native 2D array" in C++, if there is, please
reference where in the standard it is specified.

Regardless, if you can show an interface that can work for "native 2D
arrays", row-major, column-major and sparse arrays, then you will have
taught me something very cool. I'd love to see it.
Jan 2 '07 #42

P: n/a

Gianni Mariani wrote:
>
Now, if I create a bunch o 2D array templates, they will work fine with
both the new Array2D or a native 2D array. Do that with the (,) syntax!
That is the only strength it has over () while suffering deficiencies
already iterated many times in this group and in the FAQ. _If_
backwards compatibility is the single most important issue you face
then it is probably appropriate to mimic a compatible interface.
Otherwise I think the other issues far outweigh this one, narrow
requirement.
>

It's just easier all the way around.
Only given a very specific set of needs...not "all the way around."

Jan 2 '07 #43

P: n/a
Noah Roberts wrote:
....
>
Frankly I don't think vector<boolshould exist, at least not any
differently than any other type of vector. It throws a wrench into the
whole works and makes it impossible to create a real vector<bool>.
I agree - but that is what the standard is.
Jan 2 '07 #44

P: n/a

Daniel T. wrote:
Regardless, if you can show an interface that can work for "native 2D
arrays", row-major, column-major and sparse arrays, then you will have
taught me something very cool. I'd love to see it.
Simply returning a "row_reference" from operator[] that itself has an
operator[] will allow you to do these things. It's just a might bit
more complex than the alternative and thus is a less optimal solution
unless truely needed.

class col_mjr_mtx
{
...
reference_type ref(int x, int y);
row_reference operator[](int x) { return rowref<col_mjr_mtx>(this, x);
}
};

template < typename T >
class rowref
{
T * mtx;
int row;

public:
...
typename T::reference_type operator[](int y) { return mtx->ref(row,
y); }
};

See, no big deal but is most easily implemented in terms of a function
or functor op call.

Jan 2 '07 #45

P: n/a
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
....
I don't believe there is a "native 2D array" in C++, if there is, please
reference where in the standard it is specified.
Here:
T x[2][2];
>
Regardless, if you can show an interface that can work for "native 2D
arrays", row-major, column-major and sparse arrays, then you will have
taught me something very cool. I'd love to see it.
<brain dump - be warned>

template <typename T>
class array2d
{
..... I'll let someone else fill in the blanks ...
..... const/non_const constructors etc ....

T & operator()( int, int );

deref_proxy operator[]( int i )
{
return deref_proxy( i, * this );
}

class deref_proxy
{
int i;
array2d & a;
inline deref_proxy( int ii, array2d & ia )
: i( ii ), a( ia )
{
}
public:
inline T & operator[]( int j )
{
return a(j,i);
}
};
};

In a micro-detail perspective, what the proxy does is collect the
arguments to the (,) call and calls it when it has all the info. Tests
I did a while back with popular compilers is that the assembly code
generated is identical. The proxy has no overhead whatsoever.

Hence, anything that can implemented with (,) I can also implement with
[][] with negligible if any performance issues. QED.


Jan 2 '07 #46

P: n/a
Gianni Mariani <gi*******@mariani.wswrote:
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
...
I don't believe there is a "native 2D array" in C++, if there is, please
reference where in the standard it is specified.

Here:
T x[2][2];
How is that a reference in the standard? I don't believe the C++
standard defines multi-dimensional arrays at all. I may be wrong on this
point and if so, someone please correct me.
Regardless, if you can show an interface that can work for "native 2D
arrays", row-major, column-major and sparse arrays, then you will have
taught me something very cool. I'd love to see it.

<brain dump - be warned>
[snipped brain dump]

Now it is me who should have read the FAQ. :-) The procedure you
outlined is exactly what the FAQ recommends in item 13.12.

However, you have needlessly complicated your class simply to support a
particular syntax. It seems that for you, it *is* all about the syntax,
and you are willing to jump through a few hoops to support that syntax.
For me, if presented with a class like your array2d, I'll just call the
(,) directly rather than going through the proxy.

One last note, your array2d with proxy still doesn't support the
"native" 2d syntax... The below doesn't compile.

void foo( int b[] );

int main() {
array2d<inta( 10, 10 );
foo( a[3] );
}

So the reason you are supporting this particular syntax (so it will work
like "native" 2d arrays) doesn't fly.
Jan 3 '07 #47

P: n/a
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
Daniel T. wrote:
Gianni Mariani <gi*******@mariani.wswrote:
...
I don't believe there is a "native 2D array" in C++, if there is, please
reference where in the standard it is specified.
Here:
T x[2][2];

How is that a reference in the standard? I don't believe the C++
standard defines multi-dimensional arrays at all. I may be wrong on this
point and if so, someone please correct me.
I don't you're making a distiction that has any relevant consequences.
Clearly multi-dimensional arrays have been implemented as arrays of
arrays for many years. Having a semantic argument about arrays of
arrays vs multi-dimensional arrays does not help your (,) argument.
The rule is that [][] is far more common than (,) for writing matrix
code.
>
Regardless, if you can show an interface that can work for "native 2D
arrays", row-major, column-major and sparse arrays, then you will have
taught me something very cool. I'd love to see it.
<brain dump - be warned>
[snipped brain dump]

Now it is me who should have read the FAQ. :-) The procedure you
outlined is exactly what the FAQ recommends in item 13.12.

However, you have needlessly complicated your class simply to support a
particular syntax. It seems that for you, it *is* all about the syntax,
and you are willing to jump through a few hoops to support that syntax.
For me, if presented with a class like your array2d, I'll just call the
(,) directly rather than going through the proxy.
Let's see if we disagree on any of these statements:

a) in C and in C++ matricies have been traditionally supported using
[][] (array of array) syntax. Hence there is a non-trivial body of
code and knowledge that is using [][] as opposed to (,).

b) Because of proxy classes, [][] is exactly equivalent in
functionality to (,) or perhaps even a superset. (BTW, I did confirm
again on gcc that the proxy class [][] creates exactly the same
instructions as (,). - I have attached the code example below).

c) Many standard matrix operations will be coded in templates
(multiples, inverses etc).

d) Many of these "matrix" templates can be used to operate on legacy C
and C++ code as well as newer code using proxy (or non proxy array
classes like the OP code) using [][].

Having shown what a proxy class might look like, you will see that all
the arguments in the FAQ (yes - all of them) supporting (,) have no
supportable rationale at all. Perhaps it's one of the most
short-sighted sections of the entire FAQ.

No generality at all is lost using [][] over (,) while the visa versa
statement is NOT true. (,) loses in 2 very significant ways.

1) new functions on older code
2) new learning curve for no real gain

I'll say it again, anying (,) can do [][] can do better.

You say "needlessly" complicated ? The complexity is in ONE place and
makes most other code easier to read. This is a Good(TM) tradeoff.
Needlessly changing a body of code using [][] to (,) is far more
complex. It's also not exactly a complex concept. Proxy classes are a
very easy concept to understand and code - after all it's only 20 lines
in this example.
One last note, your array2d with proxy still doesn't support the
"native" 2d syntax... The below doesn't compile.

void foo( int b[] );

int main() {
array2d<inta( 10, 10 );
foo( a[3] );
}

So the reason you are supporting this particular syntax (so it will work
like "native" 2d arrays) doesn't fly.
That would be easy to support using a conversion operator, however we
may or may not want to support that. That depends on the design goals
of the matrix class.

Regardless, if you really wanted to perform such operations, you can,
with constraints and contstaint violations can be compile time errors
that give you assurances that any code that does compile will do as
expected and any code that violates constraints never issues an
instruction.

------------The return of the proxy code---------

// on a FC5 machine using gcc, the instructions for the x() and y()
// functions emitted by the compiler are identical for
// optimization levels O1 and above on both IA32 and AMD64
// architectures.

template <typename T>
class array2d
{
public:

T & operator()( int, int );

class deref_proxy;

inline deref_proxy operator[]( int i )
{
return deref_proxy( i, * this );
}

class deref_proxy
{
const int i;
array2d & a;
public:
inline deref_proxy( const int ii, array2d & ia )
: i( ii ), a( ia )
{}
public:
inline T & operator[]( int j )
{
return a(i,j);
}
};

};
float y( array2d<float& a, int i, int j )
{
return a(i,j);
}

float x( array2d<float& a, int i, int j )
{
return a[i][j];
}

Jan 3 '07 #48

P: n/a
Noah Roberts wrote:
Gianni Mariani wrote:

Now, if I create a bunch o 2D array templates, they will work fine with
both the new Array2D or a native 2D array. Do that with the (,) syntax!

That is the only strength it has over () while suffering deficiencies
already iterated many times in this group and in the FAQ.
Not one of the arguments supporting the use of (,) only in the FAQ is
supportable with a coherent rationale.

As I have shown earlier in this thread, [][] and (,) are exactly the
same in funtionalitly and performance while [][] can also be a superset
if need be.
... _If_
backwards compatibility is the single most important issue you face
then it is probably appropriate to mimic a compatible interface.
Otherwise I think the other issues far outweigh this one, narrow
requirement.
That's where we disagree. There are no other issues IMHO.

Jan 3 '07 #49

P: n/a
Simon G Best wrote:
....
>
But let me ask you a question. If you use C-style subscripting, with
operator[], to access a whole row, then what do you use to access a
whole column?
Whatever you like !

a.Col(n)
a[COL+n]
a.Transpose()[n]
^a[n]
a++[n]

..... or don't provide one at all ...

Whatever tickles your fancy.

Jan 3 '07 #50

272 Replies

This discussion thread is closed

Replies have been disabled for this discussion.