Two Dimensional Array Template

M

Michael DOUBEZ

Gianni Mariani a écrit :
Daniel T. wrote:
...
On Jan 3 you said, "The FAQ does state many false claims in support of
the position of using (,) over [][]." How about you state one assertion
that is in the FAQ that you think is false and let's see what happens.
Just one of the many you say exist so we don't get too distracted.

Read this post:
http://groups.google.com.au/group/comp.lang.c++/msg/c3bbd70542232ca6?dmode=source&hl=en

I explained it all paragraph by paragraph. What more do you want ?

A critic of what you said:
- You said: "As you can see, the FAQ bases all the claims on the
false assumption that by using [][], you cannot implement optimizations
using (,)."
- The FAQ says: "The array-of-array solution obviously works, but
it is less flexible than the operator() approach. Specifically, there
are easy performance tuning tricks that can be done with the operator()
approach that are more difficult in the [][] approach, and therefore the
[][] approach is more likely to lead to bad performance, at least in
some cases."

Do you feel the gap ? The FAQ only states that is is *easier* to
optimise the (,) solution (i.e. your compiler is more likely to yield
better performances) than [][]. This is sensible: a single function call
is easier to implement, easier to understand (for a copmpiler) than
using some proxy object for accessing data.
Clearly, multi-dimensional array, matricies or whaterver your favorite
name is for these things has been traditionally the [][] flavour.

For software engineer using dense matrices perhaps but if you work with
a (20000 x 30000 double) sparse matrix, you rapidely drop the [][] notation.
Researcher in Computing Science using Matlab will certainly be more at
ease with the (,) interface.
Let's enumerate the reasons for [][].

1. [][] syntax is well understood by C++ programmers for manipulating
multi-dimensional properties. No surprises here !
If I use it and your template specialisation is a column-first I will be
surprised because, as a software engineer, I expect a row-first.
A scientist will expect a (i,j) notation and if the indices start at 1,
it is better.
2. X[a] will never be confused like X(a,b) as a function call to
function X.

All the same, X[a] calls a function and I prefer knowing it. I could
confuse it with an array (well, not really) and I hate surprises :).

Michael
 
D

Daniel T.

Axter said:
Daniel said:
If you care to deny any of the claims made in the FAQ questions
13.10-12 (and their justifications,) then please do so.

IMHO, these FAQs (13.10, 13.11, 13.12) should be deleted or modified
to include both sides of the view point for using [][] or (,)
syntax. As these FAQs stand right now, they're not written in a
manner that gives factual and BALANCE information. They're written
in a persuasive manner, which only gives one side of the facts, and
builds on a week argument for justifying using the non-standard
syntax.

Case in point:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
[13.10] How do I create a subscript operator for a Matrix class?
When you have multiple subscripts, the cleanest way to do it is with
operator() rather than with operator[]. The reason is that
operator[] always takes exactly one parameter, but operator() can
take any number of parameters.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

At worse, the above comment is false, and at best, it's misleading.

OK. Let's get a little more detailed. You quote two sentences and then
say that the "above comment" is (at least possibly) false. The last
sentence is clearly and obviously true, so I can only assume that you
are saying that the first sentence is false (or misleading.) Since the
entire FAQ (and the following two) are meant to justify that first
sentence, you are, essentially then, denying the entire justification,
including that last sentence. Which as I mention above is clearly and
obviously true... Where does that leave us?
It gives the reader the impression that the [][] syntax can not be
done, and/or that you can't create a matrix class based on that type
of syntax. That's clearly wrong.

What part of "the cleanest way" means that the other way *cannot* be
done? You are reading too much into a single sentence. The FAQ even
presents "the cleanest way" of providing the [][] interface for single
element access. If you believe the proxy solution is cleaner or even as
clean as the op() solution, then we are using radically different
definitions for the word "clean."
Then FAQ 13.11, makes the justification of using (,) based on
performance tricks, which almost nobody would ever use. I talked to
the author of the C++ FAQ, and the performance trick he was
referring to was highly dependent on a particular hardware and OS.
It was not at all portable.

There are many ways to implement a 2D array, he mentioned two and I will
even accept that his second implementation may be dependent on a
particular situation. I have mentioned in this thread 5 different
implementations (row-major, column-major, sparse, row-major ragged, and
column-major ragged) and can think of others if you wish. Any of which
may provide better performance in particular situations.

The point is, and it is a valid point, that different situations may
require different implementations. Don't box yourself in with a class
that requires you to make major changes to all client code in order to
test these other possible implementations.
FAQ [13.12], also makes the following claim:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
The problem with the "it's faster" argument is that it's not - at
least not on the latest version of two of the world's best known C++
compilers.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

Notice how the author carefully puts this in the context of two
compilers which he fails to specify. The author and I had emailed
back and forth the results of four different compilers. Some of
which contradicts the above FAQ. He claimed he was going to put the
results on the FAQ, but that was over a year ago, and I still
haven't seen anything on it.

I would like to see more of this. Please present two classes that both
provide bounds checking and encapsulate the data such that it can be
implemented in any of the 5 methods I mention above, but where the [][]
access is faster. Also, please post what compiler/platform combinations
this argument is valid in. Hopefully, someone will be able to verify
your results. This is the first possibly valid complaint I have heard so
I want to make sure it gets a thorough airing.

In essence though, I can agree with you without problems. I personally
don't care for such micro-optimizations being an argument for, or
against, anything. That would be the loss of only one justification out
of many.
Every time this subject comes up, I see plenty of developers arguing
against the non standard operator(,).
Clearly, there is not a consensus on this issue, and (IMHO) the FAQ
author should not write the C++ FAQ in a manner that would imply there
is.

I don't see that. Most developers posting to this thread, for example,
seem to be arguing that the op(,) *should* be included in a Matrix class
[though some of us would prefer using a named member-function rather
than overriding op(). That is merely a question of syntax.]

I admit that I am in the minority in saying that op[][] should not be
included. I was called on this point earlier in the thread because it is
not what the FAQ is saying.
 
M

Michael DOUBEZ

Daniel T. a écrit :
[snip]
The consensus seems to be
that both access methods should be implemented, at least in the two
dimensional case. (Which is not something I agree with, but can accept.)
[snip]

If this this the consensus (which I hope it is not) I wouldn't like to
be the poor guy who will have to explain to the customer why there are 2
interfaces for accessing the same data in nearly the same fashion.

If you really want to have both interfaces, why not delegate it to a
template legacy_array2d<class Matrix> providing a proxy calling
Matrix::eek:perator(size_t i, size_t j) ?
That way, you can even specify an accessor to have row-first for 'legacy
code' (if you really have to).

template<class Matrix,class Accessor=Row_major<Matrix> >
class legacy_array2d;

Michael
 
N

Noah Roberts

Axter said:
Noah said:
Axter said:

No, please don't. These "expert" examples are perfect examples of what
NOT to do. A much better way of implementing [][] has already been
discussed in this thread there's no need to degrade it even further.
The serious flaws in the first have been discussed ad nausium and
continue to remain unfixed. It shows numerous mistakes that catch new
developers all the time and should not be passed of as advice
ever...unless it is, "Don't do anything like this."

http://tinyurl.com/yjkzj7

Care to give specifics, or do you prefer to remain as ambiguous as the
FAQ on this matter.

No, I don't really care to spend a lot of time on it again...it's
pointless. I've already given you many specifics many times and you
choose not to give it second thought. Many of my objections can be
viewed in the code pasted in the url post and the rest can be easily
found by searching for my name and the url to your code.
 
N

Noah Roberts

Axter said:
Noah said:
Axter said:
I recommend using standard syntax [][] over the non standard ambiguous
(,) method.

There is nothing at all non-standard or ambiguous about function calls.

It's non-standard in that it's not the standard method for referencing
an array.

Example of ambiguous usage:

x = foofo(1, 3);

Is foofoo a function, or is foofoo an array. The above syntax does not
make that clear.

Nor should it so long as it does what is expected.
The following syntax is less ambiguous:
x = foofoo[1][3];

No it isn't.

Besides, the interface I advocate is not either of these:

foofo.get_element(1,3);

This is more descriptive than either of what you seem to think are the
only two options.
 
?

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

Daniel said:
others agree with you, but I'm not so sure. The consensus seems to be
that both access methods should be implemented, at least in the two
dimensional case. (Which is not something I agree with, but can accept.)

I don't see a consensus about what *should be* used. I don't say that both
access should be implemented, nor that any of them should not be
implemented. And I don't see that the majority of the people say that
things.

What I say, and I think others also says in essence, is that the arguments
in the C++ FAQ Lite against the usage of [ ] [ ] are biased and
questionables, and the redaction of the points in question tends to give
the false impression that the syntax of the interface and the details of
the implementation are directly related.

And that people can have good reasons to use the [ ] [ ] syntax, with legacy
or non-legacy code. This reasons need not to be acceptable to all people
for all his matrix-alike class to be valid. The point is not to encourage
people to use that syntax, is about to not encourage to not use it.

And a subjective note: I think that to direct several FAQ entries to the
same point, with a more emotional mood in any of them, is a symptom that
the matter has a significant irrational component in the author's point of
view.

If someone has a point against the usage of ( , ) is a completely different
topic.
 
N

Noah Roberts

Julián Albo said:
Daniel said:
others agree with you, but I'm not so sure. The consensus seems to be
that both access methods should be implemented, at least in the two
dimensional case. (Which is not something I agree with, but can accept.)

I don't see a consensus about what *should be* used. I don't say that both
access should be implemented, nor that any of them should not be
implemented. And I don't see that the majority of the people say that
things.

What I say, and I think others also says in essence, is that the arguments
in the C++ FAQ Lite against the usage of [ ] [ ] are biased and
questionables, and the redaction of the points in question tends to give
the false impression that the syntax of the interface and the details of
the implementation are directly related.

The [][] has at least one objective design flaw over (,): "message
chaining".

"This is the case in which a client has to use one object to get
another, and then use that one to get to another, etc. Any change to
the intermediate relationships causes the client to have to change."

The fix:

http://www.refactoring.com/catalog/hideDelegate.html

Of course, since there is no such thing as operator [][] to overload
there is no way to solve the design problem and implement [][].

The whole idea of having a "2D array class" stinks of "Data Class" and
"Lazy Class".
And that people can have good reasons to use the [ ] [ ] syntax, with legacy
or non-legacy code. This reasons need not to be acceptable to all people
for all his matrix-alike class to be valid. The point is not to encourage
people to use that syntax, is about to not encourage to not use it.

There may be reasons to do it that way but that does not mean it should
not be discouraged.
 
?

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

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

Do you feel the gap ? The FAQ only states that is is *easier* to
optimise the (,) solution (i.e. your compiler is more likely to yield
better performances) than [][]. This is sensible: a single function call
is easier to implement, easier to understand (for a copmpiler) than
using some proxy object for accessing data.

I don't see, and the paragraph does not explain, the relation between
flexibility and compiler tuning tricks. And is not clear at all that a main
reason to choose syntax is to avoid a bit of work to the compiler. This
argument is a mixing between implementation details of the class and the
compilers used and the syntax of the class interface.

Maybe the argument can be important for some compiler targetting some
limited platform, but there are people that says the same type of things
for exceptions or standard containers and I don't see anybody recommending
to never use him just because of that.
 
?

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

Noah said:
The [][] has at least one objective design flaw over (,): "message
chaining".
"This is the case in which a client has to use one object to get
another, and then use that one to get to another, etc. Any change to
the intermediate relationships causes the client to have to change."
The fix:
http://www.refactoring.com/catalog/hideDelegate.html
Of course, since there is no such thing as operator [][] to overload
there is no way to solve the design problem and implement [][].

You are mixing design and implementation problems and solutions. The proxy
object can be an object independently usable as row accesor or whatever or
just a hidden detail of the implementation of the [ ] [ ] operation. And
even if it is the same thing can be used as the second. The claim about
changes in the relationship forcing client code to change, when the purpose
of the relationship is to support the syntax used by client code, is
completely inadequate.
And that people can have good reasons to use the [ ] [ ] syntax, with
legacy or non-legacy code. This reasons need not to be acceptable to all
people for all his matrix-alike class to be valid. The point is not to
encourage people to use that syntax, is about to not encourage to not use
it.
There may be reasons to do it that way but that does not mean it should
not be discouraged.

No, but it must not be discouraged without good reasons. I don't have yet
seen a convincing one.
 
N

Noah Roberts

Julián Albo said:
Noah said:
The [][] has at least one objective design flaw over (,): "message
chaining".
"This is the case in which a client has to use one object to get
The claim about
changes in the relationship forcing client code to change, when the purpose
of the relationship is to support the syntax used by client code, is
completely inadequate.

If, as you just said, the only purpose of the second object in the
message chain is to support the message chain then the second object is
not doing enough to exist. It is imposing a specific set of objects as
well as set of message chains and is just one more thing to maintain,
all without providing any concrete benifit to the design of the
program.

It seems to me that the arguments for using function syntax have
concrete reasons while the argument for [][] is based solely on an
objective preference for syntax. The most compelling, subjective
reason for [][] so far is backwards compatibility with legacy code.
That's only a valid reason if you have legacy code that needs backwards
compatibility - otherwise that point is moot. It is also possible to
change legacy code so that it exhibits better design decisions.

What is a better design decision? That is partially objective as well
but there are also subjective values that can be seen in code that have
been documented as patterns, anti-patterns, and smells. Code that has
less "smell" than another can be deemed as having a better design. It
is far from a perfect science for sure but there is at least something
subjective you can hold onto and use to evaluate code design.

Nobody is saying you shouldn't implement [][] if you _have_ to. What
is being said by both the FAQ and the people arguing for a function
interface is that the function interface is a better choice when choice
is available. The arguments I have seen for [][] all boil down to
removing the choice and in those cases it is of course self-evident
that the opposite position is unarguable.
 
?

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

Noah said:
The [][] has at least one objective design flaw over (,): "message
chaining".
"This is the case in which a client has to use one object to get
The claim about
changes in the relationship forcing client code to change, when the
purpose of the relationship is to support the syntax used by client code,
is completely inadequate.
If, as you just said, the only purpose of the second object in the
message chain is to support the message chain then the second object is
not doing enough to exist. It is imposing a specific set of objects as
well as set of message chains and is just one more thing to maintain,
all without providing any concrete benifit to the design of the
program.

The concrete benefit is clear to the people that wants it: to allow the [ ]
[ ] syntax. If you have the purpose of not allow it, is clear that you will
never see that benefit.
It seems to me that the arguments for using function syntax have
concrete reasons while the argument for [][] is based solely on an
objective preference for syntax. The most compelling, subjective
reason for [][] so far is backwards compatibility with legacy code.

This thread has mentioned several times the example of the creation of
templates that works with the matrix-alike class, with arrays of arrays,
and with vectors of vectors. You may call this legacy code if you want, but
I'm sure not all people will share that opinion.
That's only a valid reason if you have legacy code that needs backwards
compatibility - otherwise that point is moot. It is also possible to
change legacy code so that it exhibits better design decisions.

Surely there are cases where the benefit does not justify the cost of the
change.
Nobody is saying you shouldn't implement [][] if you _have_ to. What
is being said by both the FAQ and the people arguing for a function
interface is that the function interface is a better choice when choice
is available.

Maybe this was the intention. In that case this threads shows that the
redaction and selection of examples is not very good for the purpose.
Sometimes people think that things are so clear that fails to see the need
for a clean explanation.
The arguments I have seen for [][] all boil down to removing the choice
and in those cases it is of course self-evident that the opposite position
is unarguable.

In that case, the redaction of many messages in this thread are also far
away to cleanly explain his points.
 
K

Kai-Uwe Bux

Daniel said:
Kai-Uwe Bux said:
Daniel said:
Daniel T. wrote:

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?

Note the "if" in the FAQ. In reasonable implementations, there
is no overhead for accessing a single element via a proxy.

The "all true Scotsman" fallacy, you are giving "reasonable" a
special definition.

Please note that I do not give any definition for "reasonable".

Of course you do. By your statement you are implying that any
implementation that does not optimize away the overhead for accessing a
single element via a proxy, no matter how standards conforming, or
amazing it may be otherwise, is not "reasonable".

Although my claim implies that, the statement I made is not a definition.
I am ready to encounter reasonable compilers that do not optimize away
the proxies. As soon as that happens, I will consider my statement
refuted. If that statement was a definition, I would not need to be ready
for that possibility.

Would you care to provide an example of a compiler (reasonable or not)
that does not make the optimization under discussion?

How about g++ with all optimizations turned off. I don't think it makes
the optimization under discussion and yet is a perfectly reasonable and
useful complier.

a) That example actually forces me to modify my claim: every reasonable
compiler *allows* for optimizing away the proxy objects. It still follows
that fear about performance overhead due to [][] vs (,) is misplaced.

b) Here are the actual performance data from the test code in

http://groups.google.com/group/comp...Bux+Steinbach+proxies&rnum=2#cecce09e32c2dfc6

news_group> g++ -o a.out alf_008.cc
news_group> g++ -DUSE_PROXY -o b.out alf_008.cc
news_group> time a.out
did not use proxy 0

real 0m18.746s
user 0m18.229s
sys 0m0.468s
news_group> time b.out
used proxy 0

real 0m21.587s
user 0m21.121s
sys 0m0.464s
news_group> time a.out
did not use proxy 0

real 0m18.735s
user 0m18.285s
sys 0m0.444s
news_group> time b.out
used proxy 0

real 0m21.583s
user 0m20.953s
sys 0m0.628s

The program does matrix multiplication and the inner loop has two element
accesses, one multiplication and one addition plus checks for termination.
This is about as little as one can do with dereferenced elements. Even in
this case, the performance overhead is not that big: 10% abstraction
overhead.

Can I consider your lack of answer, agreement?

Almost: I do agree that without the optimization, the proxy solution will
*likely* be slower. Many factors other than optimization can influence the
speed of a program. As with all performance statements, I would use
measurement and profiling to be sure.

To me the situation looks as follows:

a) proxies provide very useful syntactic sugar for linear algebra.
b) even with very simple minded proxy implementations, [][] is not
slower than (,).

Item (b) is incorrect for all standards conforming compilers,

Did you mean "may be false for some standard conforming compilers"?

I meant "is not true for all possible standards conforming compilers".
So I think that means yes.
Also, do you happen to know an actual standard conforming compiler, for
which the statement (b) is false?

As mentioned above, g++ with all optimizations turned off.

Do you also know one that will not optimize the performance overhead away
even when you turn optimization on?

As for (a)... Several other languages, including ones that are
specifically designed for numeric computation and scientific computing
do not use [][]. Beliavsky mentioned in this thread, "[Fortran,] S (the
language of S-Plus and R), Matlab, Python/Numpy, and Visual Basic also
use commas to delimit the dimensions of an array, even when they use []
rather than () to enclose the subscripts. a[j][k] is awkward
compared to a[i,j,k] or a(i,j,k) IMO."


(a) does not talk about [][] versus (,).


So it is irrelevant to the discussion at hand.


That depends on how narrowly you define the topic of the discussion. If you
consider the veracity of the FAQ as the topic at hand, and if you consider
the rationales provided by the FAQ as claims of the FAQ, then (a) is
relevant as the FAQ creates the impression that your life would be simpler
without the proxy classes.

Since I was quoting Beliavsky, I will hope he answers. I haven't
programmed in Fortran since the early '80s.

He did. I shall quote:

Beliavsky said:
Fortran 90+, Matlab, S, and Python/Numpy allow this, using a[i,:] and
a[:,i] to refer to row or column i, except that Fortran uses () instead
of [] and S uses a[i,] and a[,i], dropping the colon. The languages
also allow one to refer to sections such as a[i1:i2, j1:j2:jstep].

Why/how is [][] more "useful" syntacticly than (,)?

It's not---well: asside from generic algorithms templates that could work
with, e.g., double[m][n] as well as any matrix class offering [][].

And the FAQ does make an exception for legacy code. To assert that *new
code* should use arrays of arrays is to deny FAQ 34.1.

I fail to see how this is only related to legacy code. vector< vector< float
is a perfect example of a 2D-array that offers [][] but not (,). If you
program generic matrix algorithms, why would you want to exclude this data
structure?

Personally, I do not put much weight on this feature. Others, who have a
different code base, however, may find this a major point attracting them
to [][] notation.
Agreed.

My main issue with the FAQ entry on matrices is that it creates the
misguided impression that element access (although of course an
important primitive) is the main issue in interface design for a
matrix class.

I don't agree here. I will agree that the FAQ creates the impression
that single element access is the main confusion of designing a matrix
class and from the longevity of this thread that assumption seems
justified.
The main flaw of the FAQ is to focus on a minor design issue and
draw general recommendations (e.g., against row proxies) from a
rather narrow minded discussion.

A minor design issue that none the less obviously draws a lot of heat.

Nonetheless it is a flaw of the FAQ not to present a better balanced account
of row and column proxies but to create the impression that the only reason
for those classes is to support [][]. Only from that false premise does the
false claim follow that your life would be easier without the proxies.

Several of us have suggested that a matrix class simply isn't complete
until a function exists for direct single element access (either op() or
some have suggested a named function such as 'at',) you seem to be among
that number. Thus you agree with the FAQ in general.

No, I agree with a point in the FAQ that I consider minor (namely that some
simple access for matrix coefficients is a nice thing to have). I disagree
with the FAQ on this issue in general as I do not think it provides a good
discussion of interface design for a matrix class. The FAQ is simply
missing the big picture of how to design a matrix class. It zooms in on a
stupid little thing; and reading just the FAQ will leave you clueless as to
what a good matrix interface looks like. In particular, you might disregard
introducing row and column proxies because the FAQ did not discuss them
fairly.

On a more philosophical level, the FAQ chooses the wrong perspective: it
discusses the ease for the programmer of the matrix class but ignores
completely the ease for the client of the matrix class. As far as library
design is concerned, I disagree with this point of view. Thus, I definitely
do not "agree with the FAQ in general" on this issue.

However, a matrix
class can be considered complete without array of array access. As long
as single element access through op() or whatever is implemented, the
proxies can be written as completely separate objects.

Of course you can write a wrapper matrix class based upon a basic_matrix
class. That is a viable design. However, it does not demonstrate that the
basic_matrix class is a well-designed matrix class. This structure is
nothing but an implementation detail of the full-fledged matrix class.

The main thrust of the FAQ is how to implement single element access
(How do I create a subscript operator for a Matrix class?), what we
learn is that performance wise, "the operator() approach is never worse
than, and sometimes better than, the [][] approach." That is something
that simply cannot be said the other way around, at least not for all
possible standards conforming compilers.

The relevance of a statement about all possible (as opposed to all actual)
compilers when it comes to performance considerations is highly doubtfull.
What matters is whether people can be expected to run into performance
problems. The optimization techniques that prevent this are well known and
widely implemented.

Also, this could easily be a case of premature optimization.

As an analogy, it would be like people arguing against having 'empty()'
in container classes because, after all, 'size()' exists and we can
always check 'size()' against 0. 'empty()' was added to containers, and
should be used, because it may be faster in some implementations and
will never be slower.

That analogy breaks down because there are containers for which the
performance difference cannot be undone even by the best optimizing
compilers: size()==0 could be linear for lists where empty() is still
constant time. On the other hand, [][] and (,) are both linear in simple
minded implementations of row proxies.


Best

Kai-Uwe Bux
 
N

Noah Roberts

Julián Albo said:
Noah said:
The [][] has at least one objective design flaw over (,): "message
chaining".
"This is the case in which a client has to use one object to get
The claim about
changes in the relationship forcing client code to change, when the
purpose of the relationship is to support the syntax used by client code,
is completely inadequate.
If, as you just said, the only purpose of the second object in the
message chain is to support the message chain then the second object is
not doing enough to exist. It is imposing a specific set of objects as
well as set of message chains and is just one more thing to maintain,
all without providing any concrete benifit to the design of the
program.

The concrete benefit is clear to the people that wants it: to allow the [ ]
[ ] syntax.

That's a circular argument. We should have [][] to have [][] does not
a valid point make. All you are saying is that it is an objective
decision based solely on preference - which is exactly what I said.
If you have the purpose of not allow it, is clear that you will
never see that benefit.

What benifit? Is there a benifit to having [][] that is objective and
distinct from just to have it?
It seems to me that the arguments for using function syntax have
concrete reasons while the argument for [][] is based solely on an
objective preference for syntax. The most compelling, subjective
reason for [][] so far is backwards compatibility with legacy code.

This thread has mentioned several times the example of the creation of
templates that works with the matrix-alike class, with arrays of arrays,
and with vectors of vectors. You may call this legacy code if you want, but
I'm sure not all people will share that opinion.

Just because it can be done doesn't mean it should be. Just because
you *can* write code that depends on that interface doesn't mean it is
a good idea. If there is a reason why you should write a bunch of
primitive dependant code for what should be an abstraction I'm all
ears. Obviously you _can_ write such code. The question isn't, "can
I," but, "should I."

In other words, if your matrix class can be treated like an array then
why isn't it one? Don't you think it might be a little better if your
matrix class used the code in question on its internal data rather than
having client code depend on this relationship always existing and
being the most appropriate method of performing the operations in
question?
Surely there are cases where the benefit does not justify the cost of the
change.

Again, just another argument based on removal of choice. If you have
no choice you have no choice. What's your point?
Nobody is saying you shouldn't implement [][] if you _have_ to. What
is being said by both the FAQ and the people arguing for a function
interface is that the function interface is a better choice when choice
is available.

Maybe this was the intention. In that case this threads shows that the
redaction and selection of examples is not very good for the purpose.
Sometimes people think that things are so clear that fails to see the need
for a clean explanation.

I see nothing unclear or ambiguous about the FAQ. It is quite clearly
worded and to the point. It even states clearly:

"Having said all that, if you find yourself maintaining a billion-line
app where the original team used m[j], or even if you are writing a
brand new app and you just plain want to use m[j], you can still
encapsulate the data structure and/or check all your parameters. "
The arguments I have seen for [][] all boil down to removing the choice
and in those cases it is of course self-evident that the opposite position
is unarguable.

In that case, the redaction of many messages in this thread are also far
away to cleanly explain his points.

That sentance makes no sense at all. Talk about being unclear...
 
G

Gianni Mariani

Daniel said:
Gianni Mariani said:
Daniel T. wrote:
...
On Jan 3 you said, "The FAQ does state many false claims in support of
the position of using (,) over [][]." How about you state one assertion
that is in the FAQ that you think is false and let's see what happens.
Just one of the many you say exist so we don't get too distracted.
Read this post:
http://groups.google.com.au/group/comp.lang.c++/msg/c3bbd70542232ca6?dmode=sou
rce&hl=en

I explained it all paragraph by paragraph. What more do you want ?

Thanks. When you posted that, I said then that 13.11 specifically says
in its opening paragraph that it is "all about" a specific
implementation of [][], the kind of implementation that started this
thread. You assert in your post that this FAQ doesn't apply to all
possible implementations of [][] and I (and the FAQ itself) agree... it
was never meant to.

You continually agree with the FAQ in detail (witness the code you
posted,)

Daniel, you must reflect more clearly on the logic arguments because you
clearly don't use have a grasp of simple logic as has been pointed out
before. This is the third time you have brought up my example code to
support your argument in an "there exsists therefore you agree" type of
fashion. Using your same logic argument I can say "I can post bad code -
therefore I think the FAQ is bad". That's about the same as the
statement you have just made. I con only assume from now on that you're
too emotionally linked to this issue and are now unable to make further
rational judgements.
... and argue against straw men (the above referenced post,) while
telling us that using a single function call to index into a
multi-dimensional array should not be allowed. You also claim that
others agree with you, but I'm not so sure.

I think no-one with a rational logic ability disagrees that the FAQ
13.10-12 need fixing.
... The consensus seems to be
that both access methods should be implemented, at least in the two
dimensional case. (Which is not something I agree with, but can accept.)

You say, "there is no good reason to use (,)." The FAQ states numerous
reasons but apparently you don't think any of them are "good". Why is it
that you think an implementor should not allow a user to access a single
element of a multi-dimensional array through a single function call?

State all the reasons from the FAQ itself. You will find that there are
none that are correct. (unless you use faulty logic in which case I
could make any conclusion I want)
 
A

Axter

Noah said:
Axter said:
Noah said:
Axter wrote:

I recommend using standard syntax [][] over the non standard ambiguous
(,) method.

There is nothing at all non-standard or ambiguous about function calls.

It's non-standard in that it's not the standard method for referencing
an array.

Example of ambiguous usage:

x = foofo(1, 3);

Is foofoo a function, or is foofoo an array. The above syntax does not
make that clear.

Nor should it so long as it does what is expected.
The following syntax is less ambiguous:
x = foofoo[1][3];

No it isn't.

Besides, the interface I advocate is not either of these:

foofo.get_element(1,3);

This is more descriptive than either of what you seem to think are the
only two options.

No, the FAQ is the one written as though those were the only two
options, and my comments are referring to the FAQ, and not your posted
code.

I agree, that using a get_element function is much more descriptive.
However, it makes it less compatible with templates using standard
syntax to access an array.

I recommend you email the C++ FAQ author, and ask him why the FAQ is
written as though [][] and (,) are the only to possible methods.

I would recommend using a descriptive get_x function over using
operator() method.

Moreover, I think a get and set function would have more flexibility,
and it's obviously less ambiguous.
 
?

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

Noah said:
The concrete benefit is clear to the people that wants it: to allow the [
] [ ] syntax.
That's a circular argument. We should have [][] to have [][] does not
a valid point make. All you are saying is that it is an objective
decision based solely on preference - which is exactly what I said.

The point is that people can have reasons to want to have the syntax, this
reasons are the motivation to do some work to implement it. Just like
almost anything. All you are saying is that if they have not a reason, they
have not. And a possible reason was in the next paragraph.
Just because it can be done doesn't mean it should be.

And just the fact that you think that it should not be done, not make it
true.
Don't you think it might be a little better if your matrix class used the
code in question on its internal data rather than having client code
depend on this relationship always existing and being the most appropriate
method of performing the operations in question?

It might, it might not. I'm not considering myself able to judge all
decisions all programmers and designers in the world take in all cases
without knowing nothing about him.

And I don't see more inconvenient in that relationship than in providing any
other way to access individual elements in the matrix-alike. That way the
discussion will be not about the convenient syntax for a matrix-alike
class, will be about the convenience of having such type of class, a
completely different question. If some class must not expose his data as
elements indexed by row and column, surely exposing it with [ ] [ ] or with
( , ) makes no difference.
Again, just another argument based on removal of choice. If you have
no choice you have no choice. What's your point?

What removal of choice? You can choice what design decisions to take in each
work without a priory deciding without good reasons that some technique can
not be good in any case, this is precisely my point. If the estimation of
the cost of each alternative were an exact science, maybe the argument than
an alternative is always better than the other can be proved. In the real
world I think is not and someone must make the choice with the better
information available in each case. If your point is that this is not a
choice but a constraint, I just disagree with that view.
I see nothing unclear or ambiguous about the FAQ. It is quite clearly
worded and to the point. It even states clearly:
"Having said all that, if you find yourself maintaining a billion-line
app where the original team used m[j], or even if you are writing a
brand new app and you just plain want to use m[j], you can still
encapsulate the data structure and/or check all your parameters. "


The unclear point in this paragraph can be: acknowledged that you can still
encapsulate and check with the [ ] [ ] syntax, why do you said all that
about the possible ways of not doing it as justification against his usage?
 
M

Michael DOUBEZ

Julián Albo a écrit :
Michael said:
- The FAQ says: "The array-of-array solution obviously works, but
it is less flexible than the operator() approach. Specifically, there
are easy performance tuning tricks that can be done with the operator()
approach that are more difficult in the [][] approach, and therefore the
[][] approach is more likely to lead to bad performance, at least in
some cases."

Do you feel the gap ? The FAQ only states that is is *easier* to
optimise the (,) solution (i.e. your compiler is more likely to yield
better performances) than [][]. This is sensible: a single function call
is easier to implement, easier to understand (for a copmpiler) than
using some proxy object for accessing data.

I don't see, and the paragraph does not explain, the relation between
flexibility and compiler tuning tricks.

I imagine that the FAQ frame it this way to say that an optimal [][]
operation (i.e. using arrays of arrays wouldn't be flexible enough
because of cases like sparse matrices, diagonal matrices, Column major
layout ... The flexible alternative (using a proxy class) is less
*likely* to be optimized than a single function call.

Exemple code:
optimal (in the idea at least):
vector<int>& Matrix::eek:perator[](size_t i);
flexible:
Matrix::Array& Matrix::eek:perator[](size_t i);
int& Matrix::Array::eek:perator[](size_t j);

In the first case, at best it is equivalent to a POD [][] but limited to
dense matrices.
In the second case, at best it is inlined across two function call.
And is not clear at all that a main
reason to choose syntax is to avoid a bit of work to the compiler. This
argument is a mixing between implementation details of the class and the
compilers used and the syntax of the class interface.

Well, it is more than a bit of work.

It is similar to the classical class arithmetic:
with given values:
intClass a(1);
intClass b(2);
the following:
intClass c;
c=a+b;
is less likely to be optimized than
intClass c(a);
a+=b;
because of intermediary objects.

If the compiler is smart enough, both writing are equivalent and in our
case, optimizing out a proxy class (by removing it completely) would be
really great (at least I don't count on it in this case).

yet again: the point is there are design more or less likely to be
optimized depending on the compiler abilities. And if you have the
choice (putting apart legacy and all specific need), why make your life
miserable ? Especially in matrix arithmetic where algorithm use a huge
amount of access and algorithm are in O(n*m) (for dense matrix at least)
when it is not worse.

The FAQ doesn't forbid but point out the choice to make. It may seem
partial because the choice is pretty straightforward.
Maybe the argument can be important for some compiler targetting some
limited platform, but there are people that says the same type of things
for exceptions or standard containers and I don't see anybody recommending
to never use him just because of that.

If there is no optimisation problem and the majority of compiler do it.
Good! But is it the case *now* ? Perhaps now or in the future but I
don't take risk for nothing.
Exception and containers are 2 other matters:
- exception because it is using known costly operation (RTTI,
ressource tracking ...)
-containers because they implement optimally (I hope) algorithms in
a generic way (the only bottleneck is then the compiler).


Michael
 
?

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

Michael said:
I don't see, and the paragraph does not explain, the relation between
flexibility and compiler tuning tricks.
I imagine that the FAQ frame it this way to say that an optimal [][]
operation (i.e. using arrays of arrays wouldn't be flexible enough
because of cases like sparse matrices, diagonal matrices, Column major
layout ... The flexible alternative (using a proxy class) is less
*likely* to be optimized than a single function call.

But it says the contrary: "The array-of-array solution obviously works, but
it is less flexible than the operator() approach". I wonder what concept of
flexibility is being used.
Well, it is more than a bit of work.

Is a work the compilers are already expected to do, in order to generate
fast code with ensambles of algorithms, containers and his iterators,
ligators, adaptors... And I don't see any recommendation against writing
code like that just because some compilers maybe don't do a good work with
him. I suppose the assumption is that people that works with that systems
knows his limitations and does not expect that all code they can find will
be perfectly fine for use in it.
yet again: the point is there are design more or less likely to be
optimized depending on the compiler abilities. And if you have the
choice (putting apart legacy and all specific need), why make your life
miserable ?

Did you mean that putting apart all reasons you don't have any reason? I
just don't assume that binary point of view of "Or you have a reason that
absolutely imposes to use it, or you should not use at all". And I have not
seen any proof or argument supporting it.

By the way, we don't have seen in this thread a mention of a current c++
compiler with such limitations (other than "Disable the optimizations",
that I consider just a bad joke).
Especially in matrix arithmetic where algorithm use a huge amount of
access and algorithm are in O(n*m) (for dense matrix at least)
when it is not worse.

Supposed that you are in situation where this is a really issue, the simple
solution is not to use the [ ] [ ]. I think it has been repeated enough
times that no one here has the purpose to impose the use of that syntax.
And I suppose that a class intended to fast matrix arithmetic may use other
means for crucial operations than the public interface. I suppose that you
are not trying to imply that the mere fact of the existence of the [ ] [ ]
interface in the class will make any operation of the class slower.
The FAQ doesn't forbid but point out the choice to make.

--> [13.10] How do I create a subscript operator for a Matrix class?
--> Use operator() rather than operator[].

This does not look to me like the exposition of a choice that must be made.
Looks like an imperative.
If there is no optimisation problem and the majority of compiler do it.
Good! But is it the case *now* ? Perhaps now or in the future but I
don't take risk for nothing.

Well, nobody tries to forbid you that choice.
 
M

Michael DOUBEZ

Julián Albo a écrit :
Michael said:
I don't see, and the paragraph does not explain, the relation between
flexibility and compiler tuning tricks.
I imagine that the FAQ frame it this way to say that an optimal [][]
operation (i.e. using arrays of arrays wouldn't be flexible enough
because of cases like sparse matrices, diagonal matrices, Column major
layout ... The flexible alternative (using a proxy class) is less
*likely* to be optimized than a single function call.

But it says the contrary: "The array-of-array solution obviously works, but
it is less flexible than the operator() approach". I wonder what concept of
flexibility is being used.

As I said before, an array-of-array POD is not at all flexible because
it is not practical in a lot of matrices usually (sparse or special
construct) or with usual optimization (triangular, bi-diagonal ...).
Now, an array-of-array with a proxy class may just be as flexible as a
single call but at the cost of a proxy class maintance.

Imagine the identity matrix:
//identity matrix read-only
class Identity
{
public:
//return 1 if row=column, 0 otherwise
int operator()(size_t i, size_t j)const
{
return (i==j)?1:0;
}
};
With the [][] syntax:
//identity matrix read-only
class Identity
{
public:
//identity array read-only of row i
struct Identity_array
{
const int i_array;//current array of row
//constructor
Identity_array(int i_param):i_array(i_param)
{
}
//return 1 if row=column, 0 otherwise
int operator[](size_t j)const
{
return (i_array==j)?1:0;
}
}
//return the array functor
const Identity_array operator[](size_t i)const
{
return Identity_array(i);
}
};

It has the same functionnality and even perhaps the same optimisation
but the design and maintenance is far from flexible (main algorithm in
sub-class ...) and I haven't even yet defined a generic accessor.

Is a work the compilers are already expected to do, in order to generate
fast code with ensambles of algorithms, containers and his iterators,
ligators, adaptors... And I don't see any recommendation against writing
code like that just because some compilers maybe don't do a good work with
him.

Compiler may do a good work (even with smelly design) but yet again if I
take a risk, why do I take it ?
The recommandation is here to say that if you do so, then you have a
special need; if you use [][] without special need then you like danger
(and I won't use your code in my airplane :) )
I suppose the assumption is that people that works with that systems
knows his limitations and does not expect that all code they can find will
be perfectly fine for use in it.

In this case, one would have to test on his own compiler. It is
additionnal he may not be willing to perform.
Did you mean that putting apart all reasons you don't have any reason? I
just don't assume that binary point of view of "Or you have a reason that
absolutely imposes to use it, or you should not use at all". And I have not
seen any proof or argument supporting it.
By the way, we don't have seen in this thread a mention of a current c++
compiler with such limitations (other than "Disable the optimizations",
that I consider just a bad joke).

I am not so keen on giving ONE compiler that may do so just for the
pleasure of giving an example. The simple design and expected
optimisation arguments are enough for me.
Especially in matrix arithmetic where algorithm use a huge amount of
access and algorithm are in O(n*m) (for dense matrix at least)
when it is not worse.

Supposed that you are in situation where this is a really issue, the simple
solution is not to use the [ ] [ ]. I think it has been repeated enough
times that no one here has the purpose to impose the use of that syntax.
And I suppose that a class intended to fast matrix arithmetic may use other
means for crucial operations than the public interface.
I suppose that you
are not trying to imply that the mere fact of the existence of the [ ] [ ]
interface in the class will make any operation of the class slower.

Do you mean you will add an interface expecting nobody will use it ?
I prefer to keep my interfaces minimal. People can always extend them if
they want.
The FAQ doesn't forbid but point out the choice to make.

--> [13.10] How do I create a subscript operator for a Matrix class?
--> Use operator() rather than operator[].

This does not look to me like the exposition of a choice that must be made.
Looks like an imperative.

If you have a question, I give an answer.
If you have a problem, I propose solutions.

Here, it is a question.

Well, nobody tries to forbid you that choice.

Nobody tries to forbid you either.
 
?

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

Michael said:
I imagine that the FAQ frame it this way to say that an optimal [][]
operation (i.e. using arrays of arrays wouldn't be flexible enough
because of cases like sparse matrices, diagonal matrices, Column major
layout ... The flexible alternative (using a proxy class) is less
*likely* to be optimized than a single function call.
But it says the contrary: "The array-of-array solution obviously works,
but it is less flexible than the operator() approach". I wonder what
concept of flexibility is being used.
As I said before, an array-of-array POD is not at all flexible because

But it is talking about that? I doubt that, given that in the previous
sentence it talks about the [ ] operator in general, not just about raw
arrays. Yet again, the arguments in this point in the FAQ are a confusing
mix between syntax and implementation.
Compiler may do a good work (even with smelly design) but yet again if I
take a risk, why do I take it ?

You don't have to if you don't want. People that have a reason to do it will
evaluate if the risk is low enough to him. That is all the point, that
saying that it never be used is an inadequate over-generalization.
The recommandation is here to say that if you do so, then you have a
special need; if you use [][] without special need then you like danger

So the point is just to be able to call 'special' to other people's reasons?
I am not so keen on giving ONE compiler that may do so just for the
pleasure of giving an example. The simple design and expected
optimisation arguments are enough for me.

Perfectly fine for you, but hardly a good argument to satisfactory prove the
point for the world in general.
Do you mean you will add an interface expecting nobody will use it ?

Do you mean that if you don't like it then nobody will use it?
The FAQ doesn't forbid but point out the choice to make.
--> [13.10] How do I create a subscript operator for a Matrix class?
--> Use operator() rather than operator[].
This does not look to me like the exposition of a choice that must be
made. Looks like an imperative.
If you have a question, I give an answer.
If you have a problem, I propose solutions.

If the proposition looks bad to some people, is criticized.
Here, it is a question.

Yes, that is the 'Q' in 'FAQ'. Nothing new here.
 

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,774
Messages
2,569,596
Members
45,130
Latest member
MitchellTe
Top