Two Dimensional Array Template

S

Simon G Best

Daniel said:
It is important to note that the FAQ is not comparing two syntaxes, but
two implementations. On the one hand having an op[] that returns a
reference to an array object or a raw array (something I think we can
both agree is a bad idea,) on the other hand not doing so.

Actually, those FAQs confuse implementation with interface. That is a
Bad Thing.

Simon
 
S

Simon G Best

Noah said:
Gianni said:
You still have not explained why array of array syntax is any less
expressive than matrix(,). They not only seem interchangeable in a
programming sense, but also in a theoretical sense. Metaphorically
speaking, instead of taking the horse to the straw, take the straw to
the horse.

Actually, since [][] is shown to be the more complex answer, no matter
how much or little, it is on you to show that (,) is less expressive.
....

With [], I can treat a two-dimensional array as a one-dimensional array,
each element happening to be a one-dimensional array. How do you do
that with (,)? Seems to me that [][] is not only as expressive as (,),
but actually more expressive!

Simon
 
Z

Z.Meson

Gianni said:
http://72.14.253.104/search?q=cache...tures/lecture03.ppt+&hl=en&gl=us&ct=clnk&cd=8

A snippet says:
"Warning about declaring matrices in C
matrix m[4][4] can be accesses as m[ i ] [ j ], but this accesses
the ith column and the jth row of the OpenGL transformation matrix

Because C convention is opposite the OpenGL convention, m[16]
is recommended declaration"

Yes - openGL matrices are transposed depending on how you look at it.

Well, you're the one that chose OpenGL as a counter-example. It didn't
take me long to find material on the web recommending against [][]
syntax for OpenGL.

Gianni said:
a) This is comp.lang.c++ where C++ is topical, if it's impossible in C
it really does not matter as far as this discussion is concerned. (,)
is just as impossible as [][] is in C anyway.

I seem to remember *you* bringing up the topic of C:

- >>> Gianni Mariani wrote:
- >>>> 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 (,).

Second of all, (,) is not impossible in C -- C uses function calls
which in its very nature uses (,).

b) most of the opengl code I have seen uses float matrix[4][4]

Don't blame me for hanging around the wrong crowd. Seriously though,
why are there people in both C and C++ recommending against the [][]
syntax for OpenGL (which you selected as a topic), scientific C and C++
libraries, and for matrices in general?
c) if you read the FAQ, it is sparse on reason and the reasons mentioned
in FAQ 13.11 are debunked in FAQ 13.12. There are no technical reasons
to use (,) over [][].

Sure, if you like (,), knock yourself out but don't spread
misinformation about technical superiority of (,) over [][] because
there simply isn't any. The only cogent arguments of any weight go in
favour of [][] instead of (,).

Hold on just a second. You're the one spreading misinformation here.
Not everyone in the world works on a PC or Mac or has access to GCC or
MS compilers. There are many, many embedded OSes with C++ compilers
that don't know how to optimize very well, and those proxy classes of
yours will not be optimized away on those platforms. Saying "the
compiler will just optimize away" is never in general a safe statement.

And let's not forget the cost of writing and maintaining proxy classes.
Sure, it adds a bit of syntactic sugar, but honestly there's a high
amount of cost to maintaining those proxy classes. And then what
happens when we get to tensors? Should we be writing embedded proxy
classes to handle [][][], [][][][], and [][][][][] syntax (and beyond)?
Using brackets for C++ for higher dimensions quickly becomes
unwieldly!

- Kevin Hall
 
D

Daniel T.

Simon G Best said:
Noah said:
Gianni said:
You still have not explained why array of array syntax is any less
expressive than matrix(,). They not only seem interchangeable in a
programming sense, but also in a theoretical sense. Metaphorically
speaking, instead of taking the horse to the straw, take the straw to
the horse.

Actually, since [][] is shown to be the more complex answer, no matter
how much or little, it is on you to show that (,) is less expressive.
...

With [], I can treat a two-dimensional array as a one-dimensional array,
each element happening to be a one-dimensional array. How do you do
that with (,)? Seems to me that [][] is not only as expressive as (,),
but actually more expressive!

With the proxy solution that Gianni showed, one cannot use [][] in the
way you describe above.

With the solution that Peter presented, one can do what you describe,
but such a solution cannot be easily converted to column major or sparse
form.

The best solution, of course, is to have a member-function that returns
a particular row or column needed.
 
D

Daniel T.

Simon G Best said:
Daniel said:
It is important to note that the FAQ is not comparing two syntaxes, but
two implementations. On the one hand having an op[] that returns a
reference to an array object or a raw array (something I think we can
both agree is a bad idea,) on the other hand not doing so.

Actually, those FAQs confuse implementation with interface. That is a
Bad Thing.

No, they don't. The FAQs address an issue where some people
inappropriately expose an implementation in a misguided effort to use a
particular interface.
 
D

Daniel T.

Kai-Uwe Bux said:
Noah said:
Julián Albo said:
Noah Roberts wrote:

Since [][] is a chaining of function calls, and not a single
call, it requires an additional object which (,) does not.
[][] requires this extra object while (,) simply does not
preclude it. Since it requires less and imposes no more it is
the more abstract solution.

This is a detail of the implementation that has no relation with
the level of abstraction.

The extra object is exposed in the interface. If it has no
relation to the abstraction it has no business in the interface
and again (,) is the better alternative.

But of course row proxies have a relation to the matrix abstraction.
What makes a matrix a 2-dimensional array is that it has rows and
columns. Any interface that does not provide a way of addressing
these important sum-matrices as some type of vector is very
low-level.

The matrix class I use has row and column proxies. You can get a row
by the row() method and a column by the column() method. It happens
that operator[] returns a row proxy. The main advantage of the proxy
classes is not that they allow [][] notation but lies in the way
they enrich the interface.

From the FAQ:
In particular, if these inner array-like objects end up allocating
their own block of memory for their row [or column] of the matrix,
the performance overhead for creating / destroying your matrix
objects can grow dramatically.

If I want to access just one element in the array, must I create a row
or column proxy?
 
S

Simon G Best

Daniel said:
Simon G Best said:
Noah Roberts wrote: ....
Actually, since [][] is shown to be the more complex answer, no matter
how much or little, it is on you to show that (,) is less expressive.
...

With [], I can treat a two-dimensional array as a one-dimensional array,
each element happening to be a one-dimensional array. How do you do
that with (,)? Seems to me that [][] is not only as expressive as (,),
but actually more expressive!

With the proxy solution that Gianni showed, one cannot use [][] in the
way you describe above.

Well, the proxy solution that Gianni posted was just a quick
illustration of the basic idea. It was far from complete! If it's done
properly, you can have the two-dimensional array /looking like/ a
one-dimensional array (/from the outside/, of course), with each row
/looking like/ a one-dimensional array as well. (Of course, you can't
get it to look absolutely like a one-dimensional, C-style array, because
it isn't a C-style array. (Perhaps I should say, 'looking like a
std::vector<>'.) But since we're not getting our fingers dirty with the
innards of such things (because we respect encapsulation), that
shouldn't be an issue.)
With the solution that Peter presented, one can do what you describe,
but such a solution cannot be easily converted to column major or sparse
form.

Indeed. I entirely agree that exposing the implementation in the
interface that way is a bad idea.
The best solution, of course, is to have a member-function that returns
a particular row or column needed.

How will you do that without using proxies?

Anyway, if you can do it with, say, row() and col() member functions,
then you can certainly do it with operator[], because you can just
define operator[] to inline to a call to row().

Simon
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Daniel said:
With [], I can treat a two-dimensional array as a one-dimensional array,
each element happening to be a one-dimensional array. How do you do
that with (,)? Seems to me that [][] is not only as expressive as (,),
but actually more expressive!
With the proxy solution that Gianni showed, one cannot use [][] in the
way you describe above.

You can make the proxy transparent, or make and document it as usable as a
row accessor, at your election. But doing it that way or by means or a row
() member function, is again just a matter or syntax preferences, not a
substantial difference between designs.
 
D

Daniel T.

Simon G Best said:
Daniel said:
The best solution, of course, is to have a member-function that returns
a particular row or column needed.

How will you do that without using proxies?

Anyway, if you can do it with, say, row() and col() member functions,
then you can certainly do it with operator[], because you can just
define operator[] to inline to a call to row().

And once again, the op[] becomes merely a notational convenience for
those who like the syntax or to accommodate legacy code.
 
N

Noah Roberts

Kai-Uwe Bux said:
Noah said:
Julián Albo said:
Noah Roberts wrote:

Since [][] is a chaining of function calls, and not a single call, it
requires an additional object which (,) does not. [][] requires this
extra object while (,) simply does not preclude it. Since it requires
less and imposes no more it is the more abstract solution.

This is a detail of the implementation that has no relation with the
level of abstraction.

The extra object is exposed in the interface. If it has no relation to
the abstraction it has no business in the interface and again (,) is
the better alternative.

But of course row proxies have a relation to the matrix abstraction. What
makes a matrix a 2-dimensional array is that it has rows and columns. Any
interface that does not provide a way of addressing these important
sum-matrices as some type of vector is very low-level.

The matrix class I use has row and column proxies. You can get a row by the
row() method and a column by the column() method. It happens that
operator[] returns a row proxy. The main advantage of the proxy classes is
not that they allow [][] notation but lies in the way they enrich the
interface. For instance, I can say

swap( A.row(i), A.row(j) );

Yes, accessing row and column objects is likely needed in a matrix.
You are likely to want both at different times. For instance,
multiplying two matrices involves taking a row from one site, a column
from another, multiplying them and repeating. So there should be a
column vector object as well. Since there are two, and only one
operator[], it makes more sense to do what you have done above and not
pick one to get the [] interface.

Like Daniel said as well, there if there is no need you shouldn't have
to pay the cost. This is rather fundamental to C++. If you don't need
row/column objects you shouldn't have to allocate them. Yes, this can
be sped up quite a bit through even more complexity and become a rather
negligable cost in runtime but the principles still hold.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Daniel said:
From the FAQ:
In particular, if these inner array-like objects end up allocating
their own block of memory for their row [or column] of the matrix,
the performance overhead for creating / destroying your matrix
objects can grow dramatically.

This is another misguided point, IMO. An enumeration of the bad ways a thing
can be implemented serves no purpose. You can make such lists for all
features of C++ and his standard library, for example. And is against the
spirit of C++ to discard things just because they can be used erroneously.
 
S

Simon G Best

Daniel said:
Simon G Best said:
Daniel said:
It is important to note that the FAQ is not comparing two syntaxes, but
two implementations. On the one hand having an op[] that returns a
reference to an array object or a raw array (something I think we can
both agree is a bad idea,) on the other hand not doing so.
Actually, those FAQs confuse implementation with interface. That is a
Bad Thing.

No, they don't.

Okay, perhaps they don't (much). But there does seem to be more concern
about implementation from implementers' perspectives than on the
interface from users' perspectives, even though they're clearly
interface questions. Using operator() as part of the interface, instead
of operator[] with proxies (or whatever), on the basis of
implementational issues, seems dubious to me. Favouring encapsulation
(as I do), I don't think it's a good idea.
The FAQs address an issue where some people
inappropriately expose an implementation in a misguided effort to use a
particular interface.

It gets a mention (or two), but that doesn't really seem to be what
they're about. I think they'd be better if they were reworded,
rewritten to be specifically about that.

Simon
 
S

Simon G Best

Daniel said:
Kai-Uwe Bux said:
But of course row proxies have a relation to the matrix abstraction.
What makes a matrix a 2-dimensional array is that it has rows and
columns. Any interface that does not provide a way of addressing
these important sum-matrices as some type of vector is very
low-level.

The matrix class I use has row and column proxies. You can get a row
by the row() method and a column by the column() method. It happens
that operator[] returns a row proxy. The main advantage of the proxy
classes is not that they allow [][] notation but lies in the way
they enrich the interface.

From the FAQ:
In particular, if these inner array-like objects end up allocating
their own block of memory for their row [or column] of the matrix,
the performance overhead for creating / destroying your matrix
objects can grow dramatically.

"*if* these inner array-like objects end up allocating their own block
of memory for their row [or column] of the matrix..." (emphasis mine).
Why would these proxies do that? They don't need to, do they?
If I want to access just one element in the array, must I create a row
or column proxy?

Not if the interface also has operator().

Simon
 
N

Noah Roberts

Simon said:
And, of course, our new code may eventually be old code that someone
else wants to reuse in the future. For all we know, they might want to
use it with other old code that operates on one-dimensional arrays,
using []-style subscripting. They might want to treat our
two-dimensional arrays as one-dimensional arrays of rows. They might
want to treat individual rows as one-dimensional arrays. If we haven't
provided suitable []-style interfaces, it's not going to be quite so
simple (but they can always wrap our two-dimensional array in a suitable
wrapper class with the right interface).

Might, might, might...

First, might has no place in design questions. There is no "might".
There is, and there is not. Either you have a requirement for the
interface or you do not.

Second, this argument has gone on so long and stupidly because the
"might" of the situation keeps changing in order to impose [][]. In
_general_ (,) is a better solution because it is simple and safe
without adding extra crap. You want to bring up a bunch of mights,
legacy code for example, I say so what? Yeah, there are exceptions to
every generalism. Your point?

The FAQ I think is quite appropriate here. It is answering questions
in the general sense for people that come in and say, "How do I make a
2d array with operator[][]?" You see it all the time and they don't
understand the subtleties of what it is they are asking. They are
usually playing with code and using operator overloading for everything
(yeah, I did it too). Later they will learn that operator overloading
is something to be avoided...in the _general_ sense.

If the FAQ was talking about 2d arrays it would be wrong in that it
should say, "Don't make a 2d array." But it is talking about
abstractions and giving a "generally" response. I believe the
counterpoints brought up are well responded to by the answer to
question 6.16.
 
D

Daniel T.

Simon G Best said:
Not if the interface also has operator().

And once again, the whole proxy interface becomes something added to
placate those who like to use [][] and legacy code.

Is there any class that supports the [][] interface that is as flexible
as one that supports the (,) interface, but doesn't simply convert the
former to the latter?
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Daniel said:
And once again, the op[] becomes merely a notational convenience for
those who like the syntax or to accommodate legacy code.

And the ( , ) is another notation for those who like that syntax... Can
someone provide solid evidence and rational arguments in favor of his
preferred style instead of trying to blame the others? If not, better end
the discussion and rewrote the faq entry, or delete it, given that there
are no consensus in the point.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Daniel said:
Is there any class that supports the [][] interface that is as flexible
as one that supports the (,) interface, but doesn't simply convert the
former to the latter?

Any way to access an element given his row and column can be qualified as
a "simple conversion to '( , )' ", or as a "simple conversion to 'at
( , )' ", or to any other way someone thinks is "more natural" or
something.

By the way, I don't see any flexibility (or lack of it) in the ( , ) syntax.
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Noah said:
The FAQ I think is quite appropriate here.

The purpose of a FAQ entry is not to generate long discussions about his
content. This thread shows how inappropriate is, at least in his current
redaction.
 
K

Kevin Hall

Gianni said:
Noah said:
However, the standard DOES provide tools to implement functional calls
and to override a single subscript operator.

Let's see:

double matrix[4][4];

Are you saying that the code requires some kind of extra "implementation" ?

That's clearly a language supported abstraction for a matrix IMHO.

<sarchasm>

Oh yeah, the language clearly supports *that* abstraction for a matrix:

double matrix1[4][4] = {{1,2,3,4},{5,6,7,8},{9,8,7,6},{5,4,3,2}}; // OK
:)
double matrix2[4][4] = {{5,6,7,8},{1,2,3,4},{5,4,3,2},{9,8,7,6}}; // OK
:)

double matrix3 = matrix1 * matrix2; // This doesn't compile! Why not?
// I thought C++ *clearly* supported
matrix abstractions!
// $!@%^&'n C++!

matrix3 = matrix1 + matrix2; // $!@%^&!!! This doesn't work either!

matrix3 = matrix1 / matrix2; // Nor this! $!@%^&!!!

matrix3 = 1 / matrix1; // $!@%^&!!! $!@%^&!!! $!@%^&!!!

</sarchasm>

No, C++ does *NOT* support matrix abstraction!

Gianni said:
Let me see.

Programmer says: I wanna change the entire code base to use (,).
Supervisor: Why do you want to do that ?
Programmer: Because it's far better ?
Supervisor: Oh, really ! OK, what's so much better ?
Programmer: Because It's a better abstraction.
Supervisor: Sure, sounds great, why is it a better abstraction ?
Programmer: Ummm, because ...... um, it's a personal preference.
Supervisor: Go look at the bug/feature list and find some real bugs to
fix and get back to me.

Anything wrong here ?

Hmmm... Well, I think we can all agree its foolish to change existing
syntax on a large project. The above conversation would be just as
foolish if the programmer wanted to change to code base from (,) to use
[][].

Anyway, that's not what I understood this whole thread to be about. I
thought the original question was more about deciding the better design
up front. I and many others believe there is sufficient evidence to
say that (,) is the better design decision. You (and I'm sure many
others) obviously disagree. So be it. We disagree.

I can accept that you and I don't see eye-to-eye on that. But on the
side topics (such as C++ natively supporting an abstraction for
matrices), I sharply disagree with many of your assertions.

Gianni said:
Noah said:
Gianni said:
Noah Roberts wrote:
At any rate, like I said...unless you are in the situation of dealing
with legacy code there is no need to worry about it. So why go to all
the trouble of forcing the [][] issue?
I think I am clearly on the side of C++ in that [][] has been used far
more than (,) and is the default syntax. You need to make an argument to
change it from [][] which is substantiated by more than just personal
preferences.

All you keep saying...and you keep saying it as if it will make it
true...is that your side is stronger and therefor should be the
default. You have yet to show it in any way.

I have:

double matrix[4][4];

...

Again, this is *NOT* a matrix!!! You may index into it like a matrix,
but the C++ standard doesn't allow you to do matrix multiplication,
inversion, addition, etc... with this type of "matrix".

- Kevin Hall
 
S

Simon G Best

Julián Albo said:
Daniel said:
And once again, the op[] becomes merely a notational convenience for
those who like the syntax or to accommodate legacy code.

And the ( , ) is another notation for those who like that syntax...

Seems to me that if we've got to the point of having nothing better to
go on than personal preference, then we've actually succeeded in our
goal of encapsulation. This is a Good Thing :)

But I don't think it does just come down to personal preference. When
it comes to what the interface should provide, we've got various issues
to consider, and I'm sure some of it's rather political. But it is a
good thing that we've got to the point where we no longer need to
consider the internal implementation when considering what the interface
should be.

We can think of these two-dimensional arrays as the two-dimensional
arrays that they are /conceptually/, rather than as how they happen to
be implemented internally. (Indeed, this, I think, should really be the
starting point when it comes to designing interfaces in the first
place.) We could consider the contexts in which such arrays could be
used. We could consider questions of reusability, both in having these
arrays reusable in the future, and in reusing old code with these
arrays. We can also consider questions of established conventions and
customs, and stuff like that.

But, of course, just because something's provided in an interface (be it
operator() or operator[]), it doesn't mean it has to be used if there
are better alternatives. And what counts as better may well depend on
the context of use. I think it makes sense to provide an interface
which provides a number of options, including operator(), operator[]
with proxies, row() and col() with proxies, and so on. Oh, and
iterators of a few kinds could also be useful. But not to the extent of
including every little thing we can think of, of course. Just the stuff
that makes sense to include.
Can
someone provide solid evidence and rational arguments in favor of his
preferred style instead of trying to blame the others? If not, better end
the discussion and rewrote the faq entry, or delete it, given that there
are no consensus in the point.

Do you mean in favour of operator() /and not having alternatives in the
interface?/ Or just in favour of including operator() in the interface
(along with alternatives)?

Simon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top