Can we override [][] ?

J

Jim Langston

I wanted to do an operator override for [][] but couldnt' figure out the
syntax. I tried this (code that doesn't compile commented out with //:

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}

// error C2804: binary 'operator [' has too many parameters
// SPixel& operator[]( const int Row, const int Column )
// {
// return Data_[ Columns_ * Row + Column ];
// }

// error C2092: '[]' array element type cannot be function
// SPixel& operator[][]( const int Row, const int Column )

SPixel& Pixel( const int Row, const int Column )
{
return Data_[ Columns_ * Row + Column ];
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

Can we override 2d array access?
 
M

Mike Wahler

Jim Langston said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax. I tried this (code that doesn't compile commented out with //:

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}

// error C2804: binary 'operator [' has too many parameters
// SPixel& operator[]( const int Row, const int Column )
// {
// return Data_[ Columns_ * Row + Column ];
// }

// error C2092: '[]' array element type cannot be function
// SPixel& operator[][]( const int Row, const int Column )

SPixel& Pixel( const int Row, const int Column )
{
return Data_[ Columns_ * Row + Column ];
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

Can we override 2d array access?

Certainly. But...
[][] is not an operator, it's two instances of the single
operator []. If you have your operator[] do the 'right
thing', you shouldn't have any problems using expressions
such as x[], x[][], x[][][], etc. Post back if you need
more help or an example.

-Mike
 
J

Jim Langston

Mike Wahler said:
Jim Langston said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax. I tried this (code that doesn't compile commented out with //:

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}

// error C2804: binary 'operator [' has too many parameters
// SPixel& operator[]( const int Row, const int Column )
// {
// return Data_[ Columns_ * Row + Column ];
// }

// error C2092: '[]' array element type cannot be function
// SPixel& operator[][]( const int Row, const int Column )

SPixel& Pixel( const int Row, const int Column )
{
return Data_[ Columns_ * Row + Column ];
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

Can we override 2d array access?

Certainly. But...
[][] is not an operator, it's two instances of the single
operator []. If you have your operator[] do the 'right
thing', you shouldn't have any problems using expressions
such as x[], x[][], x[][][], etc. Post back if you need
more help or an example.

I had goggled for operator[] but goggle doesn't seem to index special
characters (such as '[') so the hits weren't very orderly and it took me a
long time to even find the syntax for [] My manual didn't give me any
examples, time to get a new manual.

I would need an example please, as I don't know how to override[] to accept
two paramters but you seem to indicate it is two instances of []. What is
the 'right thing' or can you direct me to a web page on the subject? As I
said, in this case Google was not my friend.
 
T

Tomás

Jim Langston posted:

I would need an example please, as I don't know how to override[] to
accept two paramters but you seem to indicate it is two instances of
[]. What is the 'right thing' or can you direct me to a web page on
the subject? As I said, in this case Google was not my friend.


I only spent fifteen minutes on this, so it's by no means perfect.

Untested code:


class ChessBoard {
public:

class Square {
public:
enum SquareContents {
empty, pawn, castle, horse, bishop, queen, king } contents;

Square &operator=( SquareContents const sc )
{
contents = sc;
return *this;
}
};


Square squares[64];


class HorizontalCoordinate {
private:

ChessBoard &cb;
unsigned const x;

public:

HorizontalCoordinate(ChessBoard &arg_cb, unsigned const arg_x)
: cb(arg_cb), x(arg_x) {}

Square &operator[]( unsigned const y )
{
return cb.squares[ x * 8 + y ];
}
};


HorizontalCoordinate operator[](unsigned const x)
{
return HorizontalCoordinate(*this, x);
}

};

int main()
{
ChessBoard board;

board[3][5] = ChessBoard::Square::bishop;
}


As you can see, a simple member function (or even function-style
operator) would probably be better.

-Tomás
 
C

Cy Edmunds

Jim Langston said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax. I tried this (code that doesn't compile commented out with //:

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}

// error C2804: binary 'operator [' has too many parameters
// SPixel& operator[]( const int Row, const int Column )
// {
// return Data_[ Columns_ * Row + Column ];
// }

// error C2092: '[]' array element type cannot be function
// SPixel& operator[][]( const int Row, const int Column )

SPixel& Pixel( const int Row, const int Column )
{
return Data_[ Columns_ * Row + Column ];
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

Can we override 2d array access?

You should declare your operator as

something operator [] (int Row);

Then "something" must define

SPixel &operator [] (int Column);

The question is, what is "something"? The best thing is probably to make it
a separate class. However, a well known cheat is to make "something" an
SPixel*, which automatically provides this second operator by the usual
rules for subscripting a pointer. Hence

SPixel *operator [] (int Row) {return Row * Columns_;}

will do it!

Cy
 
T

Tomás

Tomás posted:

I only spent fifteen minutes on this, so it's by no means perfect.


Taking Cy's trick on-board, you could change it to:


class ChessBoard {
public:

class Square {
public:
enum SquareContents {
empty, pawn, castle, horse, bishop, queen, king } contents;

Square &operator=( SquareContents const sc )
{
contents = sc;
return *this;
}
};

Square squares[64];


Square *operator[](unsigned const x)
{
return squares + 8 * (x-1);
}

};

int main()
{
ChessBoard board;

board[3][5] = ChessBoard::Square::bishop;
}


-Tomás
 
J

Jim Langston

Tomás said:
Jim Langston posted:

I would need an example please, as I don't know how to override[] to
accept two paramters but you seem to indicate it is two instances of
[]. What is the 'right thing' or can you direct me to a web page on
the subject? As I said, in this case Google was not my friend.


I only spent fifteen minutes on this, so it's by no means perfect.

Untested code:


class ChessBoard {
public:

class Square {
public:
enum SquareContents {
empty, pawn, castle, horse, bishop, queen, king } contents;

Square &operator=( SquareContents const sc )
{
contents = sc;
return *this;
}
};


Square squares[64];


class HorizontalCoordinate {
private:

ChessBoard &cb;
unsigned const x;

public:

HorizontalCoordinate(ChessBoard &arg_cb, unsigned const arg_x)
: cb(arg_cb), x(arg_x) {}

Square &operator[]( unsigned const y )
{
return cb.squares[ x * 8 + y ];
}
};


HorizontalCoordinate operator[](unsigned const x)
{
return HorizontalCoordinate(*this, x);
}

};

int main()
{
ChessBoard board;

board[3][5] = ChessBoard::Square::bishop;
}


As you can see, a simple member function (or even function-style
operator) would probably be better.

Thank you. Works well. This is my solution if anyone is interested.

union SPixel
{
struct {
unsigned char B, G, R, A;
};
unsigned long Value;
};

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}
SPixel& Pixel( const int Row, const int Column )
{
if ( Row > Rows_ || Row < 0 )
throw std::string( "Out of bounds for row" );
else if ( Column > Columns_ || Column < 0 )
throw std::string( "Out of bounds for column" );
else
return Data_[ Columns_ * Row + Column ];
}

class HorizCoord
{
public:
HorizCoord( CMyBitmap& Bitmap, const int Row ): Bitmap_( Bitmap ),
Row_( Row ) {}
SPixel& operator[]( const int Column )
{
if ( Column > Bitmap_.Columns_ || Column < 0 )
throw std::string( "Out of bounds for column" );
else
return Bitmap_.Data_[ Bitmap_.Columns_ * Row_ + Column ];
}
private:
CMyBitmap& Bitmap_;
const Row_;
};

HorizCoord operator[] (int const Row)
{
if ( Row > Rows_ || Row < 0 )
throw std::string( "Out of bounds for row" );
else
return HorizCoord(*this, Row);
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

int main()
{
SPixel Pixel;
Pixel.Value = 0x01020304;
std::cout << "0x01020304 by color: " << (int) Pixel.A << " " << (int)
Pixel.R << " " << (int) Pixel.G << " " << (int) Pixel.B << std::endl;

CMyBitmap BitMap( 100, 100 );

BitMap.Pixel(10, 10).R = 255;
BitMap.Pixel(10, 10).B = 255;
BitMap.Pixel(10, 10).G = 255;
BitMap.Pixel(10, 10).A = 255;
std::cout << "All bits set by value: " <<BitMap.Pixel(10, 10).Value <<
std::endl;

BitMap[15][15].R = 128;
BitMap[15][15].B = 129;
BitMap[15][15].G = 130;
BitMap[15][15].A = 131;
std::cout << "Set using [][]: " << BitMap.Pixel(15, 15).Value <<
std::endl;

BitMap.Pixel(20, 20).Value = 0xFFFF0000;
std::cout << "0xFFFF0000 by color: " << (int) BitMap.Pixel(20, 20).A <<
" " << (int) BitMap.Pixel(20, 20).R << " " << (int) BitMap.Pixel(20, 20).G
<< " " << (int) BitMap.Pixel(20, 20).B << std::endl;

// Lets just prove that Intel is Bigendian.
unsigned char* pchar = reinterpret_cast<unsigned char*>(
&(BitMap.Pixel( 20, 20 ).Value ) );
std::cout << "First Byte:" << (int) *(pchar++) << std::endl;
std::cout << "Second Byte:" << (int) *(pchar++) << std::endl;
std::cout << "Third Byte:" << (int) *(pchar++) << std::endl;
std::cout << "Fourth Byte:" << (int) *pchar << std::endl;

std::string wait;
std::cin >> wait;
}
 
J

Jim Langston

Cy Edmunds said:
Jim Langston said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax. I tried this (code that doesn't compile commented out with //:

class CMyBitmap
{
public:
CMyBitmap( int Rows, int Columns ): Rows_( Rows ), Columns_( Columns )
{
Data_ = new SPixel[ Rows * Columns ];
}
~CMyBitmap()
{
delete[] Data_;
}

// error C2804: binary 'operator [' has too many parameters
// SPixel& operator[]( const int Row, const int Column )
// {
// return Data_[ Columns_ * Row + Column ];
// }

// error C2092: '[]' array element type cannot be function
// SPixel& operator[][]( const int Row, const int Column )

SPixel& Pixel( const int Row, const int Column )
{
return Data_[ Columns_ * Row + Column ];
}

private:
SPixel* Data_;
int Rows_;
int Columns_;

// No copy or assignment yet so disable by making private.
CMyBitmap ( CMyBitmap const& ) {};
CMyBitmap& operator=( CMyBitmap const& ) {};

};

Can we override 2d array access?

You should declare your operator as

something operator [] (int Row);

Then "something" must define

SPixel &operator [] (int Column);

The question is, what is "something"? The best thing is probably to make
it a separate class. However, a well known cheat is to make "something" an
SPixel*, which automatically provides this second operator by the usual
rules for subscripting a pointer. Hence

SPixel *operator [] (int Row) {return Row * Columns_;}

will do it!

This is an excellant solution, but I can't check for column overflow. I
think I'll keep the existing solution I have right now, but keep your's in
mind for other classes.

Thanks!
 
A

Axter

Noah said:
Jim said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax.

http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.10

I recommend NOT following this particular FAQ.
It uses contrive logic to support promoting the use of non-standard
syntax to reference a matrix.

I recommend using standard syntax [][] over more ambiguous ()() method.
I also recommmend using vector<vector<T> > type.

See following links for example implementations:
http://code.axter.com/dynamic_2d_array.h
http://www.codeguru.com/forum/showthread.php?t=231046
http://www.codeguru.com/forum/showthread.php?s=&threadid=297838
 
T

Tomás

Jim Langston posted:
union SPixel
{
struct {
unsigned char B, G, R, A;
};
unsigned long Value;
};


Platform-specific code, I realise. (What you're trying to do can be quite
easily achieved portably though.)


However, even if you're guaranteed that:

(1) "unsigned long" is four bytes.
(2) Your target architecture is Bigendian.

The compiler is still within its rights to put padding between any of B G
R A.

The slightly more portable solution (but still non-portable nonetheless)
would be:

struct SPixel {

unsigned long Value;

unsigned char &B, &G, &R, &A;

SPixel() :
B( reinterpret_cast<unsigned char&>(Value) ),
G( *(reinterpret_cast<unsigned char*>(&Value) + 1) ),
R( *(reinterpret_cast<unsigned char*>(&Value) + 2) ),
A( *(reinterpret_cast<unsigned char*>(&Value) + 3) )
{}
};


I'd criticise your code in a few places (in fact I'd rewrite it
altogether in a portable way), but if it gets the job done for you, then
so be it.

Expect MASSIVE problems though if you change architecture or platform.

-Tomás
 
N

Noah Roberts

Axter said:
Noah said:
Jim said:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax.

http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.10

I recommend NOT following this particular FAQ.
It uses contrive logic to support promoting the use of non-standard
syntax to reference a matrix.

"Non-standard"? Non-standard to who? Certainly not the domain which
uses subscript notation and/or M(a,b)...or the unimplmentable M[a,b].
I recommend using standard syntax [][] over more ambiguous ()() method.

"ambiguous"? What is so special about [][] that makes it less
ambiguous than ()?
I also recommmend using vector<vector<T> > type.

Can't enforce size.
Requires dynamic allocation.
Etc...etc...
See following links for example implementations:
http://code.axter.com/dynamic_2d_array.h

Above example is horrid still. Again it may track its own size but it
neither provides bounds checking nor does it provide a client interface
to retrieve bounds so there is frankly no reason for it to track its
size at all (only m_col is used and neither are accessable). The fact
that it contains redudant check for null of a pointer wouldn't be so
bad if it wasn't being passed off as an example and didn't have so many
other problems.

As for ambiguity...the comments state that, "It's also more compatible
with a C style 2D array, in that the array is in one continuous memory
block. This makes it possible to pass this array object to a C Function
that has a C-Style 2D array for a parameter." Unfortunately it doesn't
provide an interface to retrieve the m_data field and pass it to such a
function. The only way to do it is to yet again use [] in a way that
creates icky dependencies and sets a piss poor president for future
code:

cFunThatAcceptsCStyleMatrix(matrix[0]).

This class has numerous usability problems and creates too many damn
dependencies. It looks like the code a rank beginner would come up
with, exhibiting several newbie problems, yet its being passed off as
an expert example to use contrary to a FAQ written by obvious upper
level programmers. Seems to me like you might want your ducks more in
row for such an attempt.

delete [] matrix[0]; anyone?

How about this one:

dynamic_2d_array<int> m1(5,5);
dynamic_2d_array<int> *m2 = new dynamic_2d_array<int>(m1); // perfectly
reasonable thing to do...

I don't understand the reasoning behind placing operator= under the
protected safetynet either...seems more appropriate to make private to
me. Not virtual...not useful...only dangerous.

Also very incomplete but still offers several features yours does
not...unfortunately they work inconsistently. For example...getting
the size of a row is no problem but how to retrieve the row count??
Availability of row size is only due to return of [] . This dependency
is not necissary if the matrix class was just implemented more
completely. This version is better than the first but worse than
simply using vector<vector<T> > because it hides the encapsulating
vector for no reason and provides no access to necissary information
that vector would hold....yet exposes the internal vector to the
public...ick.

Also a rather inefficient implementation due to the reasons you
describe in the first...I agree that a single, contiguous array is much
more efficient.

Just a repost of the first link.

I suggest that if you are going to argue with this newsgroup's faqs you
should at least provide reasonable implementations of what you deem the
correct way. The ones you have provided are dangerous, incomplete, and
useless in the real world. Again, rank beginners often come up with
better code than your first implementation (couldn't do a whole lot
worse) and could very easily do better than the second. I have to
point out these facts because with you passing it off as an example of
'correct' coding contrary to the faq I think anyone that might not
otherwise be should be made aware of the numerous flaws in your
code...of which I only touched half.
 
N

Noah Roberts

Tomás said:
int main()
{
ChessBoard board;

board[3][5] = ChessBoard::Square::bishop;
}


As you can see, a simple member function (or even function-style
operator) would probably be better.

Yes. The concept of forcing [][] on an object because it is
implemented with an array is inherently flawed. Try implementing [][]
with a bitboard for example and then compare that implementation to
functional notation.

class Board
{
private:

uint64 white_pieces;
uint64 black_pieces;
uint64 white_knights;
....


? operator[](uint row);

// easier and more appropriate:
piece pieceAt(uint row, uint col);
piece operator()(uint row, uint col);
};

There is question of how piece would be found and what it is but the
client doesn't need to worry on that. Doesn't require a bunch of extra
proxy wrappers to forcably create an unnatural syntax and doesn't clue
the client in nor cause them to depend upon the internal representation
of this Board class.

Now, in actually building a chess engine you're probably going to break
encapsulation anyway and create massive dependencies just to speed
things up a hair (if you've never done it let me tell you that a LOT of
time is spent trying to get just a little more oomph out of your
classes) but at any rate this is a perfect example of what happens when
you think, "Hey this is an array, lets make it look like one..." Well,
what happens when you decide it shouldn't be implemented with an array
anymore??
 
B

boaz_sade

Noah said:
Tomás said:
int main()
{
ChessBoard board;

board[3][5] = ChessBoard::Square::bishop;
}


As you can see, a simple member function (or even function-style
operator) would probably be better.

Yes. The concept of forcing [][] on an object because it is
implemented with an array is inherently flawed. Try implementing [][]
with a bitboard for example and then compare that implementation to
functional notation.

class Board
{
private:

uint64 white_pieces;
uint64 black_pieces;
uint64 white_knights;
....


? operator[](uint row);

// easier and more appropriate:
piece pieceAt(uint row, uint col);
piece operator()(uint row, uint col);
};

There is question of how piece would be found and what it is but the
client doesn't need to worry on that. Doesn't require a bunch of extra
proxy wrappers to forcably create an unnatural syntax and doesn't clue
the client in nor cause them to depend upon the internal representation
of this Board class.

Now, in actually building a chess engine you're probably going to break
encapsulation anyway and create massive dependencies just to speed
things up a hair (if you've never done it let me tell you that a LOT of
time is spent trying to get just a little more oomph out of your
classes) but at any rate this is a perfect example of what happens when
you think, "Hey this is an array, lets make it look like one..." Well,
what happens when you decide it shouldn't be implemented with an array
anymore??

You wrote:
"but at any rate this is a perfect example of what happens when
you think, "Hey this is an array, lets make it look like one..." Well,
what happens when you decide it shouldn't be implemented with an array
anymore?? "
I must say I cannot see your point. The rational of using operator
overloading is not whether the internals of the class are with array or
something else. It is intending to make it look like array. Anyone
using C++ is accustom to using [] for accessing continues memory. This
is why you have it in std::vector and std::string but you don't at
std::list. The point is to use a code that it is easier to read. If we
were using FORTRAN then we may have preferred to using operator () and
not operator [] for subscripting. Anyways since other gave poor
implementations to the operator [] doesn't mean there are no other
better ones. You can take a look in Stroustrup's "The C++ programming
language" book for one good implementation using STL internals. There
is anther one in boost, and yet more in various matrix various
libraries (such as blitz++) and there are many more (tough I bet you
will find them flowed as well). This is programming and not
engineering!. There is no perfect solution, just a rational that you
may or may not accept. If one solution not suits you then you can find
anther that may.
Anyways - The main problem is the above code starts from the fact that
he using "C" prefixing in his class name - which is good indication
that he misses something important in programming. The second is that
this is "one time" solution - if you need 2D array and you need bit map
then first you have those two unrelated concepts be separately
implemented. From there you can continue. This may lead to the fact
that in this case you don't need "operator [] []" which I think too in
not relevant in this case.
 
J

Jim Langston

Noah Roberts wrote:
<snipping stuff unrelated to answer
Anyways - The main problem is the above code starts from the fact that
he using "C" prefixing in his class name - which is good indication
that he misses something important in programming. The second is that
this is "one time" solution - if you need 2D array and you need bit map
then first you have those two unrelated concepts be separately
implemented. From there you can continue. This may lead to the fact
that in this case you don't need "operator [] []" which I think too in
not relevant in this case.

Not this old argument again. This has been discussed many times in this
newsgroup, and different people prefer to distinguish classes from instances
in different ways. Some use capital letters for class names and small
letters for instant variables. Some use some form of prefix, some use some
formm of suffix. Some don't distinguish in anyway.

I prefer to use a prefix of 'C' Now, what is wrong with that? Where does
that break any rule of good programming?

And in this case the bitmap and the 2D array are not unrelated, because in
this case it's the only reason to allocate the memory. If I was doing the
full project (which I'm not) I'm sure I would totally refactor it and this
class would look totally different and be given a different name, and may
not actually exist.

This class was created because someone needed 2D array access to memory that
could be looked at as R,B,G,A values or all four values in one int. Which
is all this class does. How is the 2D array access and looking at R,B,G,A
values different in this particular case?
 
J

Jakob Bieling

Anyways - The main problem is the above code starts from the fact that
he using "C" prefixing in his class name - which is good indication
that he misses something important in programming.

What is this 'something' you are referring to? And how does it
relate to using "C" as a prefix for class names?

regards
 
A

Axter

Noah said:
Axter said:
Noah said:
Jim Langston wrote:
I wanted to do an operator override for [][] but couldnt' figure out the
syntax.

http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.10

I recommend NOT following this particular FAQ.
It uses contrive logic to support promoting the use of non-standard
syntax to reference a matrix.

"Non-standard"? Non-standard to who? Certainly not the domain which
uses subscript notation and/or M(a,b)...or the unimplmentable M[a,b].
I recommend using standard syntax [][] over more ambiguous ()() method.

"ambiguous"? What is so special about [][] that makes it less
ambiguous than ()?
I also recommmend using vector<vector<T> > type.

Can't enforce size.
Requires dynamic allocation.
Etc...etc...
See following links for example implementations:
http://code.axter.com/dynamic_2d_array.h

Above example is horrid still. Again it may track its own size but it
neither provides bounds checking nor does it provide a client interface
to retrieve bounds so there is frankly no reason for it to track its
size at all (only m_col is used and neither are accessable). The fact
that it contains redudant check for null of a pointer wouldn't be so
bad if it wasn't being passed off as an example and didn't have so many
other problems.

The purpose of the dynamic_2d_array, is to give a dynamic version of a
static size C-style array.
It's no more or no less safer then using a static C-Style array, and
therefore, no more horrid then using a static size C-Style array.
If you need something that requires bounds checking, then you should
not use it.
The class is not intended for that purpose.
Also very incomplete

These are example skeleton classes. They don't have to be complete.
They just need enough to get the point across as to how to get a [][]
interface.
Also a rather inefficient implementation due to the reasons you
describe in the first...I agree that a single, contiguous array is much
more efficient.

I heard this from most programmers, who don't have the experience in
actually testing this theory out.
I've conducted test, shows your above comment to be false.
Try testing this in RELEASE version, and you'll find very little
difference in performance.
In fact, some implementations have better performance with a
then with a contiguous array. said:
I suggest that if you are going to argue with this newsgroup's faqs you
should at least provide reasonable implementations of what you deem the
correct way.

I suggest, that you first test your theories before making performance
claims on this newsgroup.
The implementations I posted as examples, are reasonable for their
purpose.

useless in the real world.

And again, they're no more dangerous then using static size C-Style
arrays.
It's incorrect to believe that all code requires bounds checking.
That's why the C++ standard doesn't require that STL have bounds
checking.
If' it's good for the standard, then it's good for a skeleton example
implementation.

Following an FAQ blindly, is a mistake.
This C++ FAQ is created by one person, and he is no more or no less
prone to mistakes then any other experience programmer.

IMHO, this FAQ is wrong, and I posted alternative skeleton examples
that can be used as a template for user's custom matrix class.

IMHO, your nonconstructive comments do a disservice to the C++
community and to this newsgroup.
 
B

boaz_sade

Jakob said:
What is this 'something' you are referring to? And how does it
relate to using "C" as a prefix for class names?

regards
The reason you can find in MFC class names prefixing with C in their
names is that when Microsoft implemented MFC namespaces were not widely
supported in many compilers. In order to have their class names unique
they used C prefix to all MFC class names. Many inexperience
programmers seeing the practices from Microsoft and following them
blindly. I believe that anyone who is doing those king if thing is
missing a key understanding in using whatever tool he/she is trying to
use.
Basically it's should bather anyone seeing others placing their own
code under namespace std just because the standard library is doing it
too
Hope that now you can understand why I think this is truly a band
practice
 
B

boaz_sade

Jim said:
Noah Roberts wrote:
<snipping stuff unrelated to answer
Anyways - The main problem is the above code starts from the fact that
he using "C" prefixing in his class name - which is good indication
that he misses something important in programming. The second is that
this is "one time" solution - if you need 2D array and you need bit map
then first you have those two unrelated concepts be separately
implemented. From there you can continue. This may lead to the fact
that in this case you don't need "operator [] []" which I think too in
not relevant in this case.

Not this old argument again. This has been discussed many times in this
newsgroup, and different people prefer to distinguish classes from instances
in different ways. Some use capital letters for class names and small
letters for instant variables. Some use some form of prefix, some use some
formm of suffix. Some don't distinguish in anyway.

I prefer to use a prefix of 'C' Now, what is wrong with that? Where does
that break any rule of good programming?

And in this case the bitmap and the 2D array are not unrelated, because in
this case it's the only reason to allocate the memory. If I was doing the
full project (which I'm not) I'm sure I would totally refactor it and this
class would look totally different and be given a different name, and may
not actually exist.

This class was created because someone needed 2D array access to memory that
could be looked at as R,B,G,A values or all four values in one int. Which
is all this class does. How is the 2D array access and looking at R,B,G,A
values different in this particular case?

As for the C prefix see my replay to someone else bellow. As for the
Bitmap - why should we care about how do store it. You can the 2D
matrix is your own care so use it as "as - a". But more generally,
sometime in the future you will need 2D matrix for other use and then
you will simply write anther implementation of 2D matrix for this other
use. 2D matrix is one concept that can be used for many application in
which bitmap is just one of them. A good programmer will write 2D
matrix class (or better yet find good code writing by someone like the
boost people or other experience programmers) and concentrated he/her
efforts on the "real" code of the project - in this case the bit map
algorithm itself.
Good luck :)
 
E

Earl Purple

FYI my own matrix class allows both syntaxes.

operator[] returns a (template) class, known either as
portable_ref_buffer or portable_cref_buffer. These are standalone
classes that are used in other places as well. Both have a pointer and
length but with portable_ref_buffer the pointer is non-const, and
portable_cref_buffer has a constructor from portable_ref_buffer. In
both cases it's a weak pointer, i.e. the class does not own the
pointer. (thus "ref" in the name, it references its memory, And
portable because it's safely portable across libraries).

portable_cref_buffer and portable_ref_buffer both have operator[]
overloaded. In both cases the overload is a const member and returns
the pointer.

Both classes have member functions begin(), end(), empty() and size()
so can be used in algorithms like for_each. begin() is guaranteed to
return a pointer so it's safe to pass to functions that require a
pointer. If empty, begin() is safe as long as you don't attempt to
dereference it.

Both classes have an implicit constructor from a vector - either a
const or non-const reference depending on which class it is. They
cannot be resized though.
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top