Two Dimensional Array Template

?

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

Kevin said:
Personally though, I don't disagree with the FAQ Lite author. I think
he comes off strong, but I agree with what is written in the FAQ. If
this were part of a FAQ were official (i.e. something that the ISO C++
comittee had published ),

I guess that people don't personally ask questions to the committee, they
ask him for a standard.

A FAQ IMO is a bunch of frequent answers to questions, usually written more
carefully than in fast written posts. If a point does not reflect the
consensus of that frequent answers, quoting him is counterproductive with
the usual purpose of a FAQ: avoid the frequent repetition of the same
arguments.

And the criticism of a point in the document is by no means a
disqualification of the document in his entirety or his author, of course.
Said that, I also says that using as FAQ of the group, official or not, a
document whose author does not read the group is no better than using for
example the wikipedia for that purpose. At least the wikipedia encourages a
neutral point of view.
 
D

Daniel T.

Noah Roberts said:
Daniel said:
Gianni Mariani said:
Daniel T. wrote:
...

Could you? That is the exact question I'm asking. Can you come up with
an [][] interface that is the same for row major, column major and
sparse arrays that works "more directly"?

Why would you think that it can't ?

I don't know if you can or not, I'm asking if you can. The question
wasn't rhetorical, just like last time when you showed me the proxy
solution, I genuinely want to know if it can be done, and if so, what
such a solution would look like.

I already answered your question. You can do so by authoring a maze of
highly coupled classes that access the matrix internals directly....one
set per different way of implenting your matrix.

I am interested is seeing such a solution(s).
 
L

Lionel B

Daniel said:
The FAQ says this can easily be done with the (,) interface, but it can
only be done with the [][] interface if the latter adapts to the (,)
interface.
Assuming this is correct, there is no reason to use the [][] interface

The point seems to be: assuming my opinion is correct, then I'm right,
q.e.d.

No, reread the quoted statement more carefully. The point being made was:
assuming the *FAQ* is correct there is no reason to use the [][] interface.

It seems to me that the portion of the FAQ (or at least the interpretation
of the FAQ) quoted by Daniel T actually comprises two distinct claims:

(1) that (,) can easily provide an interface to a range of matrix
implementations such as row major, column major, sparse, ...

(2) that any implementation of [][] with similar capabilities will
inevitably be a "wrapper" (via proxies or whatever) for a (,) interface.

If both of these claims *are* correct then the statement "there is no
reason to use the [][] interface" becomes harder to argue against - except,
perhaps, for reasons of legacy code support or deep emotional attachment
to an alternate syntax.

Now no-one seems to have argued against point (1). Daniel T, on the other
hand, has requested (ad nauseam) that someone provide a convincing
refutation of point (2); I don't believe anyone has yet provided one.
 
D

Daniel T.

Lionel B said:
Daniel said:
The FAQ says this can easily be done with the (,) interface, but
it can only be done with the [][] interface if the latter adapts
to the (,) interface. Assuming this is correct, there is no
reason to use the [][] interface

The point seems to be: assuming my opinion is correct, then I'm
right, q.e.d.

No, reread the quoted statement more carefully. The point being made
was: assuming the *FAQ* is correct there is no reason to use the
[][] interface.

It seems to me that the portion of the FAQ (or at least the
interpretation of the FAQ) quoted by Daniel T actually comprises two
distinct claims:

(1) that (,) can easily provide an interface to a range of matrix
implementations such as row major, column major, sparse, ...

(2) that any implementation of [][] with similar capabilities will
inevitably be a "wrapper" (via proxies or whatever) for a (,)
interface.

If both of these claims *are* correct then the statement "there is
no reason to use the [][] interface" becomes harder to argue against
- except, perhaps, for reasons of legacy code support or deep
emotional attachment to an alternate syntax.

Now no-one seems to have argued against point (1). Daniel T, on the
other hand, has requested (ad nauseam) that someone provide a
convincing refutation of point (2); I don't believe anyone has yet
provided one.

I'm beginning to feel understood! Thank you Lionel for explaining my
(and the FAQs) position maybe better than I have been able to.

I feel it is also imporant to note that Gianni's assertion and code are
in complete agreement with the FAQ (the bottom of question 13.12
starting with "If you want to check the parameter without the above
overhead...") The only thing he seems to disagree with is the part about
thonking the joker in the noggin :) and the last two sentences.

Since Julián has broght up consensous in a few posts now, I must say
that I personally don't like using op() in the way the FAQ suggests in
FAQ 13.10. I prefer using a named member-function ("at" for example.)
That however, *is* purely a syntax issue so I don't see any reason to
argue "ad nauseam" about it. :)
 
S

Simon G Best

Daniel said:
We want each of our 2DArray implementations to use the same interface so
that we can easily switch out implementations then profile to see which
implementation is best for us. As the FAQ points out, this can easily be
done with the (,) interface, but it can only be done with the [][]
interface if the latter does nothing more than adapt to the (,)
interface. Assuming this is correct, there is no reason to use the [][]
interface when the (,) interface is available. (Unless, as pointed out
in the FAQ, one must adapt the interface for legacy code.)

If something in the above is not correct, then please let me know.

So, you're deciding what should go in the interface on the basis of
implementation? That *is* what you're doing.

Simon
 
S

Simon G Best

Julián Albo said:
Gianni said:
The assertion is that:

The decision to employ (,) vs [][] or both in a matrix class is usually
a personal matter or at most a situational decision (looking at
pre-existing code). As such FAQ items 13.10/13.11/13.12 need to be
revised as many false statements are made.

Completely agree, except that the mention of pre-existing code is too
narrow, they can be other factors. Be able to write template functions that
works with both the matrix class and with arrays of arrays, or vectors of
vectors, for example.

Indeed. Looking at a two-dimensional array as a one-dimensional array
of one-dimensional arrays can be very handy. Sometimes we want to apply
some operation to each row of an array, or to each column. It may even
be our reason for using a two-dimensional array in the first place.
Accordingly, we might want to treat the array as an array of rows or
columns. Of course, operator[] (unless we use different subscript types
or transpose proxies) only allows us to access either rows or columns,
but we can always have explicit row() and col() member functions, with
suitable proxies, instead.

Once we've got row() and col() in the interface, along with transpose
stuff, it really is just a few lines of code to add operator[] to cover
those times when a [] interface is expected. And those who don't like
operator[] don't have to use it.

It's almost as if we're arguing about semicolons :)

Simon
 
S

Simon G Best

Also, the argument occasionally put forward that [][] isn't worth the
trouble of implementing is also
Lionel said:
Daniel said:
The FAQ says this can easily be done with the (,) interface, but it can
only be done with the [][] interface if the latter adapts to the (,)
interface.
Assuming this is correct, there is no reason to use the [][] interface
The point seems to be: assuming my opinion is correct, then I'm right,
q.e.d.

No, reread the quoted statement more carefully. The point being made was:
assuming the *FAQ* is correct there is no reason to use the [][] interface.

It seems to me that the portion of the FAQ (or at least the interpretation
of the FAQ) quoted by Daniel T actually comprises two distinct claims:

(1) that (,) can easily provide an interface to a range of matrix
implementations such as row major, column major, sparse, ...

(2) that any implementation of [][] with similar capabilities will
inevitably be a "wrapper" (via proxies or whatever) for a (,) interface.

If both of these claims *are* correct then the statement "there is no
reason to use the [][] interface" becomes harder to argue against - except,
perhaps, for reasons of legacy code support or deep emotional attachment
to an alternate syntax.

Now no-one seems to have argued against point (1). Daniel T, on the other
hand, has requested (ad nauseam) that someone provide a convincing
refutation of point (2); I don't believe anyone has yet provided one.

Indeed, (1) is not in dispute. (2) isn't really in dispute, either.
What /is/ in dispute is whether or not we should be deciding what shall
and shall not go in the interface on the basis of such implementational
issues as in (2). (2) should be rejected as /irrelevant/ (*not*
incorrect) to the question of whether or not the interface should
support [][]. We should be looking at the issue from the outside, *not*
the inside. But Daniel T keeps banging on about (2), though :-(

Simon (Who Can't be Bothered to Snip.)
 
S

Simon G Best

Daniel said:
If all you are doing is adapting an interface, then one needs to wonder
why you are bothering to do so when the initial interface (the (,)
interface) is fine to work with directly.

But that's /not/ all I'm doing. With row() and col() (which you seem to
forget), I'm presenting the two-dimensional array as something that can
be regarded as both an array of rows /and/ an array of columns. (I
mean, isn't that a basic part of a two-dimensional array being a
two-dimensional array in the first place?) (,) doesn't provide
everything that row(), col() and their proxies provide.

Since it's quite conventional to include operator[] for one-dimensional
arrays, it makes sense to include it (and it's incredibly easy to
include as well, as it's effectively just another name for row()). And
since each row and column is also a one-dimensional array, it makes
sense to include operator[] for those, too. [][] is then just a
freebie, that just happens to do the same thing as (,). Do you really
think we should omit some or all of those operator[]s just because
someone might do something redundant with them?
Adaptors are fine in legacy code situations, but otherwise why bother?
Why not just use the (,) interface initially?
Anyway, we could always implement [][] more directly, and then
define (,) in terms of [][].

Could you? That is the exact question I'm asking. Can you come up with
an [][] interface that is the same for row major, column major and
sparse arrays that works "more directly"?

Basically, all you do is move the body of operator() into the second
operator[], and then define operator() in terms of [][]. I think that's
a bit silly, though, because operator() can easily be implemented
directly. And once you've got operator() implemented directly, it's
easy to implement the second [] in terms of (,). But the point is, *we
shouldn't be making interface decisions on the basis of such
implementation details!*

Simon
 
S

Simon G Best

Noah said:
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.

Okay, Yoda, let me put it like this.

Two-dimensional arrays should be presented as two-dimensional arrays.
Two-dimensional arrays are both arrays of rows /and/ arrays of columns,
and they should be presented as such. It's conventional to subcript
arrays through operator[], so operator[] should be provided for the
array-of-rows and array-of-colums views of two-dimensional arrays.
Similarly, as each row and each column is a one-dimensional array,
operator[] should be provided for individual rows and individual columns.

Now, of course, if we just include operator[] as considered in this
thread, we've got the problem that it only works for one of the two
views mentioned above (though we could include transposition for the
other view). In general, there's no reason to provide it for one view
and not the other, or to give preference to one view over the other.
(This is, I think, a much better argument against operator[] /as
considered in this thread/ than many of the other arguments offered.)

One way we could solve this problem is to derive our two-dimensional
array class from two interface-providing bases, one for the
array-of-rows view and one for the array-of-columns view. Each base
would then provide its own operator[] accordingly, as would the proxies
likely to be returned.

Simon
 
L

Lionel B

Daniel said:
We want each of our 2DArray implementations to use the same interface so
that we can easily switch out implementations then profile to see which
implementation is best for us. As the FAQ points out, this can easily be
done with the (,) interface, but it can only be done with the [][]
interface if the latter does nothing more than adapt to the (,)
interface. Assuming this is correct, there is no reason to use the [][]
interface when the (,) interface is available. (Unless, as pointed out
in the FAQ, one must adapt the interface for legacy code.)

If something in the above is not correct, then please let me know.

So, you're deciding what should go in the interface on the basis of
implementation? That *is* what you're doing.

Yes he is; judging by his previous posts, he would seem to be doing so on
the following basis: "all else being equal" - i.e. if there is no especial
reason[1] to use an alternate interface - we may as well go with the
interface that is simplest in terms of implementation. I don't see
anything wrong with that.

[1] eg. legacy code support, coders' sentimental attachment to a different
syntax, ...
 
L

Lionel B

Also, the argument occasionally put forward that [][] isn't worth the
trouble of implementing is also
Lionel said:
Daniel T. wrote:

The FAQ says this can easily be done with the (,) interface, but it can
only be done with the [][] interface if the latter adapts to the (,)
interface.
Assuming this is correct, there is no reason to use the [][] interface
The point seems to be: assuming my opinion is correct, then I'm right,
q.e.d.

No, reread the quoted statement more carefully. The point being made was:
assuming the *FAQ* is correct there is no reason to use the [][] interface.

It seems to me that the portion of the FAQ (or at least the interpretation
of the FAQ) quoted by Daniel T actually comprises two distinct claims:

(1) that (,) can easily provide an interface to a range of matrix
implementations such as row major, column major, sparse, ...

(2) that any implementation of [][] with similar capabilities will
inevitably be a "wrapper" (via proxies or whatever) for a (,) interface.

If both of these claims *are* correct then the statement "there is no
reason to use the [][] interface" becomes harder to argue against - except,
perhaps, for reasons of legacy code support or deep emotional attachment
to an alternate syntax.

Now no-one seems to have argued against point (1). Daniel T, on the other
hand, has requested (ad nauseam) that someone provide a convincing
refutation of point (2); I don't believe anyone has yet provided one.

Indeed, (1) is not in dispute. (2) isn't really in dispute, either.
What /is/ in dispute is whether or not we should be deciding what shall
and shall not go in the interface on the basis of such implementational
issues as in (2). (2) should be rejected as /irrelevant/ (*not*
incorrect) to the question of whether or not the interface should
support [][]. We should be looking at the issue from the outside, *not*
the inside.

[Excuse me for basically repeating my reply to a previous post of yours in
this thread.]

I agree *in general* - however there is one circumstance where I *would*
base interface on implementation, and that's where there is no reason
*not* to; eg. if there is no reason to prefer (,) over [][] or vice-versa
on any other grounds, then I will go with the interface which is *simpler
to implement* - namely (,). After all, why complicate life unnecessarily?
But Daniel T keeps banging on about (2), though :-(

I think for the above reason.
 
D

Daniel T.

Simon G Best said:
Daniel said:
We want each of our 2DArray implementations to use the same interface so
that we can easily switch out implementations then profile to see which
implementation is best for us. As the FAQ points out, this can easily be
done with the (,) interface, but it can only be done with the [][]
interface if the latter does nothing more than adapt to the (,)
interface. Assuming this is correct, there is no reason to use the [][]
interface when the (,) interface is available. (Unless, as pointed out
in the FAQ, one must adapt the interface for legacy code.)

If something in the above is not correct, then please let me know.

So, you're deciding what should go in the interface on the basis of
implementation?

Close. I'm deciding on what should go in the interface on the basis of
its flexibility in hiding the details of the implementation. I.E., on
its ability to abstract the problem space.

The interface that allows the most implementation flexibility with the
least effort is the better interface. Now in many cases, there may be
some tension between "flexibility" and "effort" (i.e., a question as to
whether the extra effort is worth the extra flexibility,) but in this
case (with the exception of legacy code situations) the more flexible
interface actually requires *less* effort.
 
S

Simon G Best

Lionel said:
So, you're deciding what should go in the interface on the basis of
implementation? That *is* what you're doing.

Yes he is; judging by his previous posts, he would seem to be doing so on
the following basis: "all else being equal" - i.e. if there is no especial
reason[1] to use an alternate interface - we may as well go with the
interface that is simplest in terms of implementation. I don't see
anything wrong with that.

[1] eg. legacy code support, coders' sentimental attachment to a different
syntax, ...

Not all else /is/ equal in this case. operator[] for the whole,
two-dimensional array presents that array as a one-dimensional array of
rows. With suitable proxies, including operator[], each row is
presented as a one-dimensional array. [][] is just a special case of
use where the second [] happens to immediately follow the first. (The
two []s could easily be applied in different functions.) (,) doesn't
present two-dimensional arrays in that way. (With (,), it's a single
call. Both subscripts have to be provided together. You can't provide
one in one function, and the second in another.)

[]-style subscripting seems to be the more general of the two, with (,)
being (almost) equivalent to just a special case of []-style subscripting.
 
S

Simon G Best

Daniel said:
Close. I'm deciding on what should go in the interface on the basis of
its flexibility in hiding the details of the implementation. I.E., on
its ability to abstract the problem space.

Since, as you've pointed out so many times, []-style subscripting can be
implemented in terms of (,), []-style subscripting must be at least as
flexible "in hiding the details of the implementation" as (,). (That
was the whole point of all that proxy stuff!!!)
The interface that allows the most implementation flexibility with the
least effort is the better interface. Now in many cases, there may be
some tension between "flexibility" and "effort" (i.e., a question as to
whether the extra effort is worth the extra flexibility,) but in this
case (with the exception of legacy code situations) the more flexible
interface actually requires *less* effort.

That's assuming that (,) is more flexible, but it isn't. Your own,
oft-repeated argument of [][] boiling down to (,) is persuasive on that
matter.

Also, something you seem to be stuck on is the idea that the two []s
have to go together. They don't. The first can be in one function, and
the second in another. And, as you /can/ use them together, [][]-style,
the []-style interface is actually /more/ general than (,), and no less
flexible.
 
S

Simon G Best

Lionel said:
[Excuse me for basically repeating my reply to a previous post of yours in
this thread.]

No worries. I believe I've just replied to that other post :)
 
?

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

Lionel said:
The FAQ says this can easily be done with the (,) interface, but it can
only be done with the [][] interface if the latter adapts to the (,)
interface.
Assuming this is correct, there is no reason to use the [][] interface
The point seems to be: assuming my opinion is correct, then I'm right,
q.e.d.
No, reread the quoted statement more carefully. The point being made was:
assuming the *FAQ* is correct there is no reason to use the [][]
interface.

Yes, but the point is made by people that agree with that point of the
document, then I assume is also his own opinion. In other words, the
reasoning is: assuming that the point of the FAQ that says there is no
reason to use [ ] [ ] is correct, then there is no reason to use [ ] [ ]
q.e.d.
It seems to me that the portion of the FAQ (or at least the interpretation
of the FAQ) quoted by Daniel T actually comprises two distinct claims:
(1) that (,) can easily provide an interface to a range of matrix
implementations such as row major, column major, sparse, ...

I think nobody question that point... Well, maybe a novice can question
the "easily" part ;-)
(2) that any implementation of [][] with similar capabilities will
inevitably be a "wrapper" (via proxies or whatever) for a (,) interface.

This is the point that has been repeated ad nauseam in this thread, but
nobody proved it nor explained his meaning. What will be the way to
establish if some implementation is a wrapper or other or not, other than
see it explicitly done that way in the code?
If both of these claims *are* correct then the statement "there is no
reason to use the [][] interface" becomes harder to argue against -
except, perhaps, for reasons of legacy code support or deep emotional
attachment to an alternate syntax.

And this is a totally subjective and unproved claim, togeher with an
ad-hominem argument, and a conclussion that is no direct consequence of the
premises.
Daniel T, on the other hand, has requested (ad nauseam) that someone
provide a convincing refutation of point (2); I don't believe anyone has
yet provided one.

Can you provide a convincing refutation of the claim "In a planet near
Sirius there are an ancient civiliaztion of reptilian looking creatures"? I
suppose no. But the absence of that refutation does not prove the claim is
true.

But if you ask for one, you must establish the conditions to distinguish
what is "really a wrapper of" and what is not. Otherwise you are asking for
another endlessly discussion that will not convince nobody.

And even supposing the claim were true, that is not a reason to ban the
usage of other syntax. There are many cases in C++ where alternative syntax
peacefully coexist.
 
L

Lionel B

Lionel said:
So, you're deciding what should go in the interface on the basis of
implementation? That *is* what you're doing.

Yes he is; judging by his previous posts, he would seem to be doing so on
the following basis: "all else being equal" - i.e. if there is no especial
reason[1] to use an alternate interface - we may as well go with the
interface that is simplest in terms of implementation. I don't see
anything wrong with that.

[1] eg. legacy code support, coders' sentimental attachment to a different
syntax, ...

Not all else /is/ equal in this case.

What is "this case"?
operator[] for the whole, two-dimensional array presents that array as a
one-dimensional array of rows. With suitable proxies, including
operator[], each row is presented as a one-dimensional array. [][] is
just a special case of use where the second [] happens to immediately
follow the first. (The two []s could easily be applied in different
functions.) (,) doesn't present two-dimensional arrays in that way.

"in that way" = "with the same interface syntax". *If* you require the
above functionality - and you may not - then you can implement it equally
with an operator(,), perhaps via row() and col() calls. The syntax then may
of course be different.
(With (,), it's a single call. Both subscripts have to be provided
together. You can't provide one in one function, and the second in
another.)

You can provide row() and col() interfaces.
[]-style subscripting seems to be the more general of the two, with (,)
being (almost) equivalent to just a special case of []-style subscripting.

....or vice-versa ;) I think we'll have to agree to disagree here.
 
S

Simon G Best

Lionel said:
What is "this case"?

Having operator[] return a proxy which has its own operator[] (and
perhaps other stuff, such as iterators,) compared with having operator()
take both subscripts together.
operator[] for the whole, two-dimensional array presents that array as a
one-dimensional array of rows. With suitable proxies, including
operator[], each row is presented as a one-dimensional array. [][] is
just a special case of use where the second [] happens to immediately
follow the first. (The two []s could easily be applied in different
functions.) (,) doesn't present two-dimensional arrays in that way.

"in that way" = "with the same interface syntax". *If* you require the
above functionality - and you may not - then you can implement it equally
with an operator(,), perhaps via row() and col() calls. The syntax then may
of course be different.

"operator(,)"? In this thread, we've ended up with "(,)" being short
for "a(i, j)"-style subscripting, with "[][]" being short for
"a[j]"-style. If you're doing, say, a.row(i), that's not (,)-style.
Of course, you can overload operator() to take just the first
subscript, but then that's []-style with () for [], and is still not
(,)-style.
 
D

Daniel T.

Simon G Best said:
Daniel said:
Close. I'm deciding on what should go in the interface on the basis of
its flexibility in hiding the details of the implementation. I.E., on
its ability to abstract the problem space.

Since, as you've pointed out so many times, []-style subscripting can be
implemented in terms of (,), []-style subscripting must be at least as
flexible "in hiding the details of the implementation" as (,). (That
was the whole point of all that proxy stuff!!!)

As flexible, but no more so. See below...
The interface that allows the most implementation flexibility with the
least effort is the better interface. Now in many cases, there may be
some tension between "flexibility" and "effort" (i.e., a question as to
whether the extra effort is worth the extra flexibility,) but in this
case (with the exception of legacy code situations) the more flexible
interface actually requires *less* effort.

That's assuming that (,) is more flexible, but it isn't. Your own,
oft-repeated argument of [][] boiling down to (,) is persuasive on that
matter.

I do not dispute that the [][] interface provided by both the FAQ and
Gianni is as flexible as the (,) interface provided by the FAQ. However,
the [][] interface provided does not add flexibility and it requires
*more* effort to create than the (,) interface provided (except in
legacy code situations.) As I say above, when comparing two equally
flexible interfaces, the one that requires less effort is the better
interface.
 
N

Noah Roberts

Simon said:
Okay, Yoda, let me put it like this.

Two-dimensional arrays should be presented as two-dimensional arrays.

Which is why I didn't bring up the point to the OP. The discussion is
now about "matrices". A two dimensional array class doesn't do enough
to warrant its existance.
Two-dimensional arrays are both arrays of rows /and/ arrays of columns,

No, they are one or the other, not both. Common convention says they
are arrays of rows.
and they should be presented as such. It's conventional to subcript
arrays through operator[], so operator[] should be provided for the
array-of-rows and array-of-colums views of two-dimensional arrays.

You can only do it once. You can't do it for both. Why should one get
preference over the other?
In general, there's no reason to provide it for one view
and not the other, or to give preference to one view over the other.
(This is, I think, a much better argument against operator[] /as
considered in this thread/ than many of the other arguments offered.)

Yeah, I made it a long time ago. I guess you're not paying attention.
One way we could solve this problem is to derive our two-dimensional
array class from two interface-providing bases, one for the
array-of-rows view and one for the array-of-columns view. Each base
would then provide its own operator[] accordingly, as would the proxies
likely to be returned.

Yeah because calling mtx.(ColMjr::eek:perator[])(5)[4], or
static_cast<ColMjr&>(mtx)[5][4] is so much more convenient than
mtx.row(5).value(4)

You guys are just too operator happy for your own good.
 

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

Forum statistics

Threads
473,813
Messages
2,569,698
Members
45,488
Latest member
MohammedHa

Latest Threads

Top