Can we override [][] ?

Discussion in 'C++' started by Jim Langston, May 31, 2006.

  1. Jim Langston

    Jim Langston Guest

    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?
     
    Jim Langston, May 31, 2006
    #1
    1. Advertising

  2. Jim Langston

    Mike Wahler Guest

    "Jim Langston" <> wrote in message
    news:KB5fg.137$...
    >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
     
    Mike Wahler, May 31, 2006
    #2
    1. Advertising

  3. Jim Langston

    Jim Langston Guest

    "Mike Wahler" <> wrote in message
    news:5I5fg.9653$...
    >
    > "Jim Langston" <> wrote in message
    > news:KB5fg.137$...
    >>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.
     
    Jim Langston, May 31, 2006
    #3
  4. Jim Langston

    Tomás Guest

    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
     
    Tomás, May 31, 2006
    #4
  5. Jim Langston

    Cy Edmunds Guest

    "Jim Langston" <> wrote in message
    news:KB5fg.137$...
    >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
     
    Cy Edmunds, May 31, 2006
    #5
  6. Jim Langston

    Noah Roberts Guest

    Noah Roberts, May 31, 2006
    #6
  7. Jim Langston

    Tomás Guest

    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
     
    Tomás, May 31, 2006
    #7
  8. Jim Langston

    Jim Langston Guest

    "Tomás" <No.Email@Address> wrote in message
    news:Tl6fg.9753$...
    > 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;
    }
     
    Jim Langston, May 31, 2006
    #8
  9. Jim Langston

    Jim Langston Guest

    "Cy Edmunds" <> wrote in message
    news:Wv6fg.9779$...
    >
    > "Jim Langston" <> wrote in message
    > news:KB5fg.137$...
    >>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!
     
    Jim Langston, May 31, 2006
    #9
  10. Jim Langston

    Axter Guest

    Noah Roberts wrote:
    > 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.

    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
     
    Axter, May 31, 2006
    #10
  11. Jim Langston

    Tomás Guest

    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
     
    Tomás, May 31, 2006
    #11
  12. Jim Langston

    Noah Roberts Guest

    Axter wrote:
    > Noah Roberts wrote:
    > > 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.

    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.

    > http://www.codeguru.com/forum/showthread.php?t=231046


    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.

    > http://www.codeguru.com/forum/showthread.php?s=&threadid=297838


    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.
     
    Noah Roberts, May 31, 2006
    #12
  13. Jim Langston

    Noah Roberts Guest

    Tomás wrote:

    > 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??
     
    Noah Roberts, May 31, 2006
    #13
  14. Jim Langston

    Guest

    Noah Roberts wrote:
    > Tomás wrote:
    >
    > > 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.
     
    , May 31, 2006
    #14
  15. Jim Langston

    Jim Langston Guest

    <> wrote in message
    news:...

    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?
     
    Jim Langston, May 31, 2006
    #15
  16. wrote:

    > 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
    --
    jb

    (reply address in rot13, unscramble first)
     
    Jakob Bieling, May 31, 2006
    #16
  17. Jim Langston

    Axter Guest

    Noah Roberts wrote:
    > Axter wrote:
    > > Noah Roberts wrote:
    > > > 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.

    > > http://www.codeguru.com/forum/showthread.php?t=231046

    >
    > 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
    vector<vector< > >, then with a contiguous array.


    > 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.


    >>The ones you have provided are dangerous, incomplete, and

    > 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.
     
    Axter, May 31, 2006
    #17
  18. Jim Langston

    Guest

    Jakob Bieling wrote:
    > wrote:
    >
    > > 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
    > --
    > jb
    >
    > (reply address in rot13, unscramble first)

    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
     
    , May 31, 2006
    #18
  19. Jim Langston

    Guest

    Jim Langston wrote:
    > <> wrote in message
    > news:...
    >
    > 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 :)
     
    , May 31, 2006
    #19
  20. Jim Langston

    Earl Purple Guest

    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.
     
    Earl Purple, May 31, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guest
    Replies:
    2
    Views:
    564
    Natty Gur
    Jul 13, 2003
  2. Guest
    Replies:
    2
    Views:
    3,121
    Guest
    Jul 16, 2003
  3. Jibba Jabba

    Can't override CSS class!!!

    Jibba Jabba, Feb 14, 2004, in forum: HTML
    Replies:
    11
    Views:
    37,081
    brandondrury
    Sep 30, 2007
  4. Nocturnal
    Replies:
    3
    Views:
    620
    Toby Inkster
    Jul 7, 2006
  5. Gali
    Replies:
    2
    Views:
    707
    Robert Klemme
    Aug 14, 2006
Loading...

Share This Page