Daniel said:
Gianni Mariani said:
Daniel said:
I don't believe there is a "native 2D array" in C++, if there is, please
reference where in the standard it is specified.
Here:
T x[2][2];
How is that a reference in the standard? I don't believe the C++
standard defines multi-dimensional arrays at all. I may be wrong on this
point and if so, someone please correct me.
I don't you're making a distiction that has any relevant consequences.
Clearly multi-dimensional arrays have been implemented as arrays of
arrays for many years. Having a semantic argument about arrays of
arrays vs multi-dimensional arrays does not help your (,) argument.
The rule is that [][] is far more common than (,) for writing matrix
code.
[snipped brain dump]
Now it is me who should have read the FAQ.
The procedure you
outlined is exactly what the FAQ recommends in item 13.12.
However, you have needlessly complicated your class simply to support a
particular syntax. It seems that for you, it *is* all about the syntax,
and you are willing to jump through a few hoops to support that syntax.
For me, if presented with a class like your array2d, I'll just call the
(,) directly rather than going through the proxy.
Let's see if we disagree on any of these statements:
a) in C and in C++ matricies have been traditionally supported using
[][] (array of array) syntax. Hence there is a non-trivial body of
code and knowledge that is using [][] as opposed to (,).
b) Because of proxy classes, [][] is exactly equivalent in
functionality to (,) or perhaps even a superset. (BTW, I did confirm
again on gcc that the proxy class [][] creates exactly the same
instructions as (,). - I have attached the code example below).
c) Many standard matrix operations will be coded in templates
(multiples, inverses etc).
d) Many of these "matrix" templates can be used to operate on legacy C
and C++ code as well as newer code using proxy (or non proxy array
classes like the OP code) using [][].
Having shown what a proxy class might look like, you will see that all
the arguments in the FAQ (yes - all of them) supporting (,) have no
supportable rationale at all. Perhaps it's one of the most
short-sighted sections of the entire FAQ.
No generality at all is lost using [][] over (,) while the visa versa
statement is NOT true. (,) loses in 2 very significant ways.
1) new functions on older code
2) new learning curve for no real gain
I'll say it again, anying (,) can do [][] can do better.
You say "needlessly" complicated ? The complexity is in ONE place and
makes most other code easier to read. This is a Good(TM) tradeoff.
Needlessly changing a body of code using [][] to (,) is far more
complex. It's also not exactly a complex concept. Proxy classes are a
very easy concept to understand and code - after all it's only 20 lines
in this example.
One last note, your array2d with proxy still doesn't support the
"native" 2d syntax... The below doesn't compile.
void foo( int b[] );
int main() {
array2d<int> a( 10, 10 );
foo( a[3] );
}
So the reason you are supporting this particular syntax (so it will work
like "native" 2d arrays) doesn't fly.
That would be easy to support using a conversion operator, however we
may or may not want to support that. That depends on the design goals
of the matrix class.
Regardless, if you really wanted to perform such operations, you can,
with constraints and contstaint violations can be compile time errors
that give you assurances that any code that does compile will do as
expected and any code that violates constraints never issues an
instruction.
------------The return of the proxy code---------
// on a FC5 machine using gcc, the instructions for the x() and y()
// functions emitted by the compiler are identical for
// optimization levels O1 and above on both IA32 and AMD64
// architectures.
template <typename T>
class array2d
{
public:
T & operator()( int, int );
class deref_proxy;
inline deref_proxy operator[]( int i )
{
return deref_proxy( i, * this );
}
class deref_proxy
{
const int i;
array2d & a;
public:
inline deref_proxy( const int ii, array2d & ia )
: i( ii ), a( ia )
{}
public:
inline T & operator[]( int j )
{
return a(i,j);
}
};
};
float y( array2d<float> & a, int i, int j )
{
return a(i,j);
}
float x( array2d<float> & a, int i, int j )
{
return a
[j];
}