Gianni said:
(x,y) does not work with legacy code or generic programming. This is a
major issue if you're looking for a general solution.
I can pretty much answer your entire post right here as this is the
main point. I have already stated that legacy code is an issue. There
is no nice way to deal with code that needs [][] especially if it was
written with C style arrays in mind. Your template classes look nice
but I believe your use of [][] was a mistake.
Now, I have already stated that legacy code or orders from on high are
one thing, but designing a mistake like this in from scratch is a big
mistake. Your template class works great and is rather efficient for C
style array and with vectors of vectors. A C function will still of
course not be able to deal with vectors of vectors so if you have to
use one you are already up shit creek.
But lets look at it from a fresh view kind of standpoint. Being as we
can set asside the issue of legacy code that depends on C style arrays
we can evaluate each implementation's merrit without artificial
requirements. When we are designing from scratch we want robust code
that is also fast. Robust in that it verifys inputs and makes sure
that clients don't try to do something they shouldn't (the argument for
robust code is pretty well known and accepted so I won't go there). We
want fast in both development and testing time as well as run time;
this means we want to do as little as possible to get the job done.
We can create our general functions with the [][] syntax or () syntax -
or with a standard function for that matter. C arrays are obviously
better suited for the [][] syntax so it might seem like the best
choice. However, objects appear to be better suited for the () syntax
for reasons that have already been gone over several times -> The only
protected way to provide [][] in an object is to create an adapter for
the () or function call interface; we can create a simpler
implementation but we expose the internals of the class and basically
ruin the whole purpose of a class so that our array would be better
just exposed and used normally (the only reasons to create an object
class is because of the protections such constructs offer - otherwise
simple functions and PODs are much better).
So, someone already showed us some basics of what would be needed to
implement the () to [][] adapter for an object and still let the class
construct do its job; it was comparitively involved and it wasn't even
finished. So, how would you make an adapter for the other method? I
myself might provide something as simple as:
template<typename T>
class CArrAdapter
{
T * data;
int col_num;
int row_num;
public:
CArrAdapter(T * d, int c, int r) : data(d), col_num(c), row_num(r) {}
T operator () (int i, int j) { if ( i > row_num || j > col_num) throw
something; return *(data + i * col_num + j); }
};
That to me looks a lot simpler, smaller, easier to test and validate,
and just all around better than the adapter required to change () into
[][].
The question now comes of "legacy" code. First off it seems rather
established that we are talking about something similar to the template
classes you posted and not something in C. The reason is simple - you
can't pass a C++ object into a C function that expects an array anyway
- no way to do it (well some very platform specific stuff might work
but lets stay simple).
The thing I like to do with "legacy" code is replace it. Not
immediately of course as time is an issue usually but as things go by I
like to fix little problems I see and eventually totally replace all
"legacy" code with something better - if necissary. So, do we want to
be stuck forever with the [][] syntax or would we eventually like to
replace it with something that is simpler but still robust? This is
when that nice () to [][] adapter comes into play nicely. Use it when
I have to, write everything new with the "better" design, and
eventually the "legacy" code and the adapter go the way of the dodo -
that includes things like those templates you posted though just going
through and changing them might be enough. This is why I feel the
"legacy" code argument is rather weak - I don't like keeping legacy
code if I don't like it and can think of something better...especially
if it gets rid of a lot of nastyness like the breaking of class
boundaries. I especially don't like to stick my design to it.
Now, you also made the claim more recently that you original code post
was not meant to be a *good* example but just a quicky. That is
reasonable, but I for one took it as your real advice and I think the
OP did as well. So then I am gathering that you see the flaw in
returning &vect
and agree that it is a problem.
At this point it is assumed that an adapter must be created either
for the object or for the array. I can't think of a decent alternative
and the only alternative offered is fundamentally flawed - you yourself
seem to now be sharing this view as you are now saying your code was
just a "quicky". So, since an adapter is required I say that the
choice is then based on which is the simpler. I would also have the
goal in mind to phaze out the use of C arrays and replace them with C++
objects eventually. My choice at that point is a given.
Now you have my logic on the matter. Either you understand or you
don't. Either you agree or you don't. I don't have any more time to
discuss this right now...the weekend is over.