Two-Dimensional Dynamic Arrays

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • roberts.noah@gmail.com

    #31
    Re: Two-Dimensional Dynamic Arrays


    Kai-Uwe Bux wrote:
    [color=blue][color=green][color=darkred]
    > >> >> >> It's quite easy to turn [A][B] into (A,B) with no loss of
    > >> >> >> performance (on a good optimizing compiler).[/color][/color][/color]
    [color=blue]
    > The statement is clearly meaningful. Whether it is true is a slightly
    > different matter. This pretty much depends on how you understand "easy". If
    > you consider writing a proxy class like the two presented complicated, you
    > will consider the statement false -- although you should agree to the
    > weaker version:
    >
    > It's *possible* to turn [A][B] into (A,B).
    >
    > This possibility has been demonstrated.[/color]

    Actually, what your proxy class did was to demonstrate that () could be
    turned into [][] as what your proxy did was to create an adapter to
    call () with the [][] interface...in other words the interface was
    changed from () TO [][], not the other way. This is a rather important
    distinction as it shows which was the more natural way to provide a
    service. It also did a good job of illistrating how this added several
    layers of totally unnecissary complexity.

    At any rate, your assertion is without meaning. Of course it is
    possible to call () with [][] or [][] with (). This does not mean the
    two are equivilent in nature. Any claim otherwise is a failure in
    logic. It is also possible to make operator * mean addition in C++,
    and much more simply in fact. Is it useful? Is it introducing or
    removing problems? Those are the questions to ask yourself.

    No matter how you choose to alter the topic of discussion it was
    certainly never asserted by anyone that it was not possible to call one
    function with another. The *possibility* of generating the classes and
    functions necissary to provide an interface for an artificially imposed
    syntax was NEVER disputed. There is no end to the stupid things that
    are *possible* to do. If that is all you have left to cling to then
    there is nothing left to argue.

    Comment

    • roberts.noah@gmail.com

      #32
      Re: Two-Dimensional Dynamic Arrays


      Axter wrote:
      [color=blue]
      > I recommend using [][] over operator(), because it's easier to read,
      > and to maintain.
      > It's also easier to port back and forth with standard C-Style 2D
      > arrays.
      >
      > See following link for efficient implementation:
      > http://code.axter.com/dynamic_2d_array.h[/color]

      This is just a reiteration of the original code. At least in this case
      though you aren't exposing internals of a class you have no control
      over but only your own. The above class has no purpose. It protects
      nothing. m_data may as well be public. That class doesn't even check
      its inputs. The only thing you could say it does is keep track of its
      2d dimensions...bu t you could do that with a struct.

      Since it exposes its internal data to the public and provides no
      protected interface to that data this class has next to no
      encapsulation. This means all clients have to manage everything.
      Better yet, you provide no way to get at necissary information that
      would allow the clients to make sure they don't send bad input to the
      class...but the class doesn't make sure its inputs are valid...in other
      words the little encapsulation the class does offer is actually bad as
      it means every client must also keep its own copy of the array bounds.

      Since each client has to track its own copies of the bounds and do its
      own error checking to make sure never to violate the exposed internals
      of the class, this class is not only unnecissary it is also a very
      inefficient implementation - a public pointer would be more efficient
      and easier to maintain. Do some casts and get your [][] syntax...

      Not very convincing.

      About [][] being easier to read. Well that is a stylistic preference
      but keep in mind two things:

      1) In math the syntax is (a,b) - though usually subscripted.
      2) Is it really that much easier to read that the added complexity
      necissary to implement it adiquately is warranted?

      About it being easier to maintain...I think you will need to elaborate
      more on this idea as I see your above cited example as being an
      absolute maintanence nightmare. Sure, the class is simple but its
      clients are going to get really messy.

      Comment

      • roberts.noah@gmail.com

        #33
        Re: Two-Dimensional Dynamic Arrays


        Kai-Uwe Bux wrote:[color=blue]
        > reasons more specific than the
        > general philosophical yadda yadda about encapsulation.[/color]

        Heh...it's no wonder I run into so much code rot in the real world.
        Encapsulation is more that "general philisophical yadda yadda." It is
        the sole purpose of classes and the very foundation of OOP. A class
        that doesn't encapsulate its data is like a cell with no wall. When a
        cell has no wall its insides just kind of meander about to god only
        knows where....sort of like sauce in a bowl of spaghetti.

        I can't believe I wasted so much time arguing with people that don't
        even understand the importance of so simple a concept. If you don't
        understand this concept and its importance then there is no way you can
        understand the reasoning in the FAQ entry I cited or why returning
        &array[x] is horrid.

        No wonder...

        hehehehe I've been bashing my head against the brick wall of
        newbieville.

        Comment

        • Gianni Mariani

          #34
          Re: Two-Dimensional Dynamic Arrays

          roberts.noah@gm ail.com wrote:[color=blue]
          > Gianni Mariani wrote:[/color]
          ....[color=blue]
          > You truely are lost. Go back to school. A -> B therefore C is not
          > valid logic.[/color]

          Another fact free statement, let's see how many facts we can actually
          find in this posting.
          [color=blue]
          >
          >[color=green]
          >>Within entire FAQ, it has not given one thing you can do with "(,)" that
          >>you cannot do with "[][]" yet it claims that "(,)" has a potential
          >>upside. I still claim that there exists code that would take longer to
          >>convert to "(,)" and will work with "[][]". I can even implement "[][]"
          >>in tems of "(,)" which means that anything that you can do with "(,)"
          >>can be done with "[][]".[/color]
          >
          >
          > You are wrong here ...[/color]

          This is gong to be rich.
          [color=blue]
          > ... again and again the point has just gone right past
          > you without one iota of understanding or even a hint that you realized
          > it was there. [][] by its definition creates an internal dependency
          > unless you create some, totally unnecissary to the task, proxy to
          > artificially impose the syntax paradigm in an abstract manner that in
          > the end just uses the more appropriate syntax of (x,y).[/color]

          "unnecissar y" - I'm not sure I think you know what that means.

          Wether somthing is needed is determined by design.
          [color=blue]
          >
          > In other words, and hopefully ones you can understand this time as they
          > are in the FAQ and have been reiterated several times here, there is no
          > way to change the form of the matrix storage once you have created [][]
          > as you have done.[/color]

          .... Give me any implementation that takes a (,) and it can be turned
          into a [][] with no loss in performance. They ARE THE SAME THING except
          that [][] is more commonly found in numeric code written in C or C++
          which means less porting, easier templates, yadda yadda, There is NO
          GOOD REASON to use (,).
          [color=blue]
          > ... You can't then decide that the computer would be
          > able to compute things faster if the matrix was stored in column major
          > form because all clients would then, necissarily, have to change! This
          > is unacceptable; a change to the private internals of a class should
          > NEVER affect its users.[/color]

          Again, the only logical way you can get to this conclusion is if there
          was somthing different between [][] and (,). You have already admitted
          that there is no essential difference so another fact free statement.
          [color=blue]
          > ... Creating a proxy answers this problem by
          > returning an object that just stores X and calls (x,y) on the matrix to
          > return the appropriate value. This is totally unnecissary and only
          > adds to the complexity of the program without giving any real benefit -[/color]

          (x,y) does not work with legacy code or generic programming. This is a
          major issue if you're looking for a general solution.
          [color=blue]
          > all it does is provide a particular syntax for minds too closed to
          > realize it is easier, and more efficient, the other way.[/color]

          a) easier is a matter of opinion
          b) efficient is a fallacy

          More fact free statements.
          [color=blue]
          > ... If there is
          > some reason why [][] MUST be used (some screwed up 3rd party lib,
          > orders from on high or whatever)[/color]

          How about the C++ standard ?

          float matricks[3][4];

          .... try referencing matricks using (,).

          There is a plethora of already written code that uses [][]. Unless
          there is a good reason to change it, then don't.
          [color=blue]
          > ... then you better provide it, and a
          > proxy (or adapter) seems like a good way of doing so, but starting from
          > scratch and imposing this mistake is a big mistake.[/color]

          Consider this:
          template <typename T>
          struct matrix_traits;

          template <typename w_Type >
          struct matrix_traits< matrix< w_Type > >
          {
          typedef w_Type value_type;

          static unsigned rows(
          const matrix< w_Type > & i_matrix
          )
          {
          return i_matrix.m_rows ;
          }

          static unsigned columns(
          const matrix< w_Type > & i_matrix
          )
          {
          return i_matrix.m_colu mns;
          }
          };

          template <typename w_Type, int w_rows, int w_columns>
          struct matrix_traits< w_Type [w_rows][w_columns] >
          {
          typedef w_Type value_type;

          static unsigned rows(
          const w_Type (&i_array)[w_rows][w_columns]
          )
          {
          return w_rows;
          }

          static unsigned columns(
          const w_Type (&i_array)[w_rows][w_columns]
          )
          {
          return w_columns;
          }
          };


          template <typename TRESULT, typename T0, typename T1>
          void add_matrix(
          TRESULT & result,
          const T0 & i_arg0,
          const T1 & i_arg1
          )
          {
          assert(
          matrix_traits<T RESULT>::rows(r esult)
          == matrix_traits<T 0>::rows(i_arg0 )
          );
          assert(
          matrix_traits<T 1>::rows(i_arg1 )
          == matrix_traits<T 0>::rows(i_arg0 )
          );
          assert(
          matrix_traits<T RESULT>::column s(result)
          == matrix_traits<T 0>::columns(i_a rg0)
          );
          assert(
          matrix_traits<T 1>::columns(i_a rg1)
          == matrix_traits<T 0>::columns(i_a rg0)
          );

          for (
          unsigned l_row = matrix_traits<T 0>::rows(i_arg0 );
          0 < l_row --;
          )
          {
          for (
          unsigned l_column = matrix_traits<T 0>::columns(i_a rg0);
          0 < l_column --;
          )
          {
          result[ l_row ][ l_column ] =
          i_arg0[ l_row ][ l_column ]
          + i_arg0[ l_row ][ l_column ];
          }
          }
          }

          void add_test(
          double (&ar)[3][4],
          const double (&a0)[3][4],
          const double (&a1)[3][4]
          )
          {
          add_matrix( ar, a0, a1 );
          }

          void add_test(
          matrix<float> & ar,
          const double (&a0)[3][4],
          const double (&a1)[3][4]
          )
          {
          add_matrix( ar, a0, a1 );
          }

          The "add_matrix " method works equally as well with the matrix class as
          it would a POD matrix. This would not be true if the matrix class
          depended on (,) as the indexing syntax. This is a very significant issue.
          [color=blue]
          >
          > The code you provided to the OP is a perfect example of how NOT to
          > write good objects as it exposed the internals of not only the class
          > itself but it also exposed the internals of a class to which you have
          > no control (std::vector).. .and it did so in a manner that left the
          > class no way to protect its *private* parts from external influence.
          > This just murders all reason for using objects in the first place.[/color]

          FYI, I was not going for the best code, I was going for quick example of
          how you can make a dynamically sized matrix in the same spirit as
          std::vector. Your points are well taken. However, you can complain
          about code posted by others but you seem unwilling to post corrected
          code. If these issues irk you so much, fix it.
          [color=blue]
          > Everyone does this from time to time but it is the better programmer
          > that can see that and learn from that mistake. Hopefully the OP is
          > reading this and understands better than you and can see that you made
          > a mistake there even if you can't (or are too proud to admit).[/color]

          You're such a good programmer, we know, show us already.
          [color=blue]
          >
          > [][] doesn't even make sense for anything other than a vector that
          > contains vectors anyway - one for the vector and one for the vector it
          > contains at that index.[/color]

          Fact free statement, please explain why it makes no sense.
          [color=blue]
          > ... There is no such operator as [][][/color]

          Yep, right again. That is 2 "[]" operators. The point is ?
          [color=blue]
          > ... and imposing
          > one simply for the sake of imposing one is just silly, pointless, and
          > harmful.[/color]

          You keep on saying it's an imposition to use [][], however, I have
          stated at least 3 times now that it does make sense for legacy code and
          generic programming, I have even given you an example of code that works
          for both regular POD matrix and the dynamic matrix example I showed
          earlier in this post. You have never refuted these statements, yet you
          cast the whole idea as "rot".
          [color=blue]
          > ... It's rot, pure and simple.[/color]

          Is that a technical phrase ?

          Comment

          • Kai-Uwe Bux

            #35
            Re: Two-Dimensional Dynamic Arrays

            roberts.noah@gm ail.com wrote:
            [color=blue]
            >
            > Kai-Uwe Bux wrote:
            >[color=green][color=darkred]
            >> >> >> >> It's quite easy to turn [A][B] into (A,B) with no loss of
            >> >> >> >> performance (on a good optimizing compiler).[/color][/color]
            >[color=green]
            >> The statement is clearly meaningful. Whether it is true is a slightly
            >> different matter. This pretty much depends on how you understand "easy".
            >> If you consider writing a proxy class like the two presented complicated,
            >> you will consider the statement false -- although you should agree to the
            >> weaker version:
            >>
            >> It's *possible* to turn [A][B] into (A,B).
            >>
            >> This possibility has been demonstrated.[/color]
            >
            > Actually, what your proxy class did was to demonstrate that () could be
            > turned into [][] as what your proxy did was to create an adapter to
            > call () with the [][] interface...in other words the interface was
            > changed from () TO [][], not the other way.[/color]

            This, I guess is an ambiguity in English. Gianni Mariani clearly meant that
            the user could write

            A[row][col]

            and this expression would, by means of proxy magic, eventually result in a
            call of A(row,col). Whether you want to call that a transformation from (,)
            to [][] or a transformation from [][] to (,) seems a matter of perspective.
            [color=blue]
            > This is a rather important
            > distinction as it shows which was the more natural way to provide a
            > service. It also did a good job of illistrating how this added several
            > layers of totally unnecissary complexity.[/color]

            "Several layers" is an exaggeration.

            Whether the added complexity is unnecessary cannot be answered in the
            absolute. Very much, depends on the context. However, I would agree that
            one should not implement the proxy layer without good reason.

            The stronger claim that was made is that this is easy (somewhat a matter of
            opinion, taste, and cultural background) and can be done without
            performance penalty (a purely technical claim also stated in the FAQ
            [13.12]). I think, it is "easy" (some 40 lines of code for a little bit of
            syntactic sugar is not that big a deal to me). Moreover, Gianni Mariani has
            confirmed that, with modern compilers, one does not need to fear a loss in
            performance. So, although we may have to agree to disagree on the easyness
            part, there is a confirmation for the claim concerning performance.

            [color=blue]
            > At any rate, your assertion is without meaning. Of course it is
            > possible to call () with [][] or [][] with ().[/color]

            So, you concede that it is true. Well, then it is, a fortiori, not without
            meaning. If, however, you would be using the word "meaning" synonymous with
            "relevance" , then you have a point :-)

            The stronger claim, however, that proxies are easy to implement and can be
            done without performance penalty, is clearly relevant. In particular, it
            implies that the FAQ advice should be taken with a grain of salt as the
            purely technical discussion of performance in the FAQ applies strictly to
            simple minded, not proxy based implementations of the [][] interface (such
            as the one first given to the OP).

            [color=blue]
            > This does not mean the two are equivilent in nature.[/color]

            I don't think, I claimed that.


            However, this sub-thread started with a slight disagreement about what would
            constittue "changing the subject". I feel that that point became somewhat
            mood.

            In any case, I share your sentiment about the first matrix class as
            presented to the OP.

            As for proxy classes there are two established issues in this thread:

            a) easyness.
            b) performance.

            I would suggest to ditch (a): it is clear that proxy classes add complexity.

            I would suggest to declare that (b) should be re-evaluated when more data
            points become available.

            Finally, I would also like to open a new angle on proxies:

            c) which opportunities do proxies as part of a matrix interface offer?

            I think that it makes perfect sense to have a matrix class define types
            row_vector and col_vector and to provide full fledged expression
            templates / proxies that allow you to address the rows and columns in a
            matrix. What I am thinking of is something like this: you could express a
            row-operation as

            A[i] += 2*A[j];

            This, of course, will not work for columns. So, I would suggest member
            functions

            row_vector_prox y row ( size_type );

            and

            col_vector_prox y col ( size_type );

            Thus, the above becomes

            A.row(i) += 2 * A.row(j);

            and swapping two columns could be done via

            std::swap( A.col(i), A.col(j) );

            At some point, methinks, this can reduce the overall complexity of a matrix
            class interface. In my own matrix class, I have member functions for
            elementary row/col operations and row and column swaps. Maybe, proxies
            actually could be useful in order to reduce complexity.


            Best regards

            Kai-Uwe Bux

            Comment

            • Kai-Uwe Bux

              #36
              Re: Two-Dimensional Dynamic Arrays

              roberts.noah@gm ail.com wrote:
              [color=blue]
              >
              > Kai-Uwe Bux wrote:[color=green]
              >> reasons more specific than the
              >> general philosophical yadda yadda about encapsulation.[/color]
              >
              > Heh...it's no wonder I run into so much code rot in the real world.
              > Encapsulation is more that "general philisophical yadda yadda." It is
              > the sole purpose of classes and the very foundation of OOP. A class
              > that doesn't encapsulate its data is like a cell with no wall. When a
              > cell has no wall its insides just kind of meander about to god only
              > knows where....sort of like sauce in a bowl of spaghetti.[/color]

              Exactly, and the FAQ item I referred to provided additional reasons that are
              more specific in that they apply to matrix classes proper but not to all
              classes. Here is the complete sentence:
              [color=blue][color=green]
              >> I read the remarks about performance as giving reasons as to why you want
              >> to keep the implementation details hidden -- reasons more specific than
              >> the general philosophical yadda yadda about encapsulation.[/color][/color]

              [color=blue]
              > I can't believe I wasted so much time arguing with people that don't
              > even understand the importance of so simple a concept. If you don't
              > understand this concept and its importance then there is no way you can
              > understand the reasoning in the FAQ entry I cited or why returning
              > &array[x] is horrid.
              >
              > No wonder...
              >
              > hehehehe I've been bashing my head against the brick wall of
              > newbieville.[/color]

              Why do you insult me?


              Regards

              Kai-Uwe Bux

              Comment

              • Axter

                #37
                Re: Two-Dimensional Dynamic Arrays


                roberts.noah@gm ail.com wrote:[color=blue]
                > Axter wrote:
                >[color=green]
                > > I recommend using [][] over operator(), because it's easier to read,
                > > and to maintain.
                > > It's also easier to port back and forth with standard C-Style 2D
                > > arrays.
                > >
                > > See following link for efficient implementation:
                > > http://code.axter.com/dynamic_2d_array.h[/color]
                >
                > This is just a reiteration of the original code. At least in this case
                > though you aren't exposing internals of a class you have no control
                > over but only your own. The above class has no purpose. It protects
                > nothing. m_data may as well be public. That class doesn't even check
                > its inputs. The only thing you could say it does is keep track of its
                > 2d dimensions...bu t you could do that with a struct.
                >
                > Since it exposes its internal data to the public and provides no
                > protected interface to that data this class has next to no
                > encapsulation. This means all clients have to manage everything.
                > Better yet, you provide no way to get at necissary information that
                > would allow the clients to make sure they don't send bad input to the
                > class...but the class doesn't make sure its inputs are valid...in other
                > words the little encapsulation the class does offer is actually bad as
                > it means every client must also keep its own copy of the array bounds.
                >
                > Since each client has to track its own copies of the bounds and do its
                > own error checking to make sure never to violate the exposed internals
                > of the class, this class is not only unnecissary it is also a very
                > inefficient implementation - a public pointer would be more efficient
                > and easier to maintain. Do some casts and get your [][] syntax...
                >
                > Not very convincing.[/color]

                The purpose of the class, is not to provide bounds checking or extra
                encapsolation.
                It's purpose is to provide a basic generic frame work for an efficient
                dynamic 2D array class that can be access using normal C-Style syntax.

                Classes that attempt to do everything, end up doing nothing very
                efficient.
                [color=blue]
                >
                > About [][] being easier to read. Well that is a stylistic preference
                > but keep in mind two things:
                >
                > 1) In math the syntax is (a,b) - though usually subscripted.[/color]

                Keep in mind, that C/C++ does not use that type of syntax, and I think
                that idea is as bad as trying to make C++ code like BASIC.
                Adding different syntax for contrived reasones, only serves to make the
                code harder to read and understand. Stick with the KISS (Keep It
                Simple Stupid) approach.
                [color=blue]
                > About it being easier to maintain...I think you will need to elaborate
                > more on this idea as I see your above cited example as being an
                > absolute maintanence nightmare. Sure, the class is simple but its
                > clients are going to get really messy.[/color]

                I think you should provide an example as how this simple generic class
                would be a nightmare to maintain, anymore then using a generic class
                like std::vector.

                IMHO, the idea of using operator() for a 2D array is a very bad idea,
                and does not work well with the generic programming model. There is no
                real legitimate reason for promoting operator() use over [][] in
                generic programming.
                On this matter, the C++ FAQ is very wrong.

                Comment

                • roberts.noah@gmail.com

                  #38
                  Re: Two-Dimensional Dynamic Arrays


                  Axter wrote:
                  [color=blue]
                  > I think you should provide an example as how this simple generic class
                  > would be a nightmare to maintain, anymore then using a generic class
                  > like std::vector.[/color]

                  I don't. I think it sufficient to point out that, among other
                  important things, std::vector provides access to its bounds and your
                  class does not. Therefore every client of your class must have a copy
                  of the array boundaries while with std::vector they would not.
                  std::vector also does significantly more than your class including
                  growing in size and providing methods for sorting, searching, etc.
                  Your class not only doesn't do much, it doesn't do anything. It would
                  be MUCH more effecient to implement what you are doing with a simple
                  pointer and some casts.

                  I'll let the FAQ stand on its own. I don't need to defend it and it's
                  obvious to me now that I am arguing with a pack of newbies that refuse
                  to learn anything valueable. The FAQ was written by people smarter
                  and/or more experienced than either of us; I choose to learn from such
                  people so as to improve my efficiency as a professional
                  developer...esp ecially when what they say is so well stated and
                  obviously true...and I am actually more convinced of that now since the
                  only ones saying I'm wrong don't seem to understand basic concepts
                  and/or have gotten completely lost by the topic of discussion.

                  Comment

                  • peter koch

                    #39
                    Re: Two-Dimensional Dynamic Arrays


                    roberts.noah@gm ail.com skrev:
                    [color=blue]
                    > Axter wrote:
                    >[color=green]
                    > > I think you should provide an example as how this simple generic class
                    > > would be a nightmare to maintain, anymore then using a generic class
                    > > like std::vector.[/color]
                    >[/color]

                    [snip]
                    [color=blue]
                    > I'll let the FAQ stand on its own. I don't need to defend it and it's
                    > obvious to me now that I am arguing with a pack of newbies that refuse
                    > to learn anything valueable. The FAQ was written by people smarter
                    > and/or more experienced than either of us; I choose to learn from such
                    > people so as to improve my efficiency as a professional
                    > developer...esp ecially when what they say is so well stated and
                    > obviously true...and I am actually more convinced of that now since the
                    > only ones saying I'm wrong don't seem to understand basic concepts
                    > and/or have gotten completely lost by the topic of discussion.[/color]

                    Let me step in. So far as I see this thread is a rather bad attempt to
                    defend a position in the C++-faq. You seem to ignore the advice from
                    Gianni and you fail to respond to his quite reasonable arguments for
                    using operator []: namely that this allows reuse of existing code, e.g.
                    in a template library.
                    The C++ faq is very well written and invaluable for newbies and
                    programmers in the beginning of their C++ career, but that does not
                    mean that it is without flaws (*) or that it does not cut corners on
                    some of the more advanced stuff.
                    I've "known" Mariani on this newsgroup for quite some time now; he is
                    certainly not a newbie and is quite capable of writing and
                    understanding C++. If only you did care to read his posts and
                    understand them, this would be clear to you. I would recommend you to
                    cut down on your ego and learn from him.

                    /Peter

                    * If you go to the C++ faq you will find a list of recent changes.
                    Among them is a correction from ... Gianni Mariani.

                    Comment

                    • Axter

                      #40
                      Re: Two-Dimensional Dynamic Arrays


                      roberts.noah@gm ail.com wrote:[color=blue]
                      > Axter wrote:
                      >[color=green]
                      > > I think you should provide an example as how this simple generic class
                      > > would be a nightmare to maintain, anymore then using a generic class
                      > > like std::vector.[/color]
                      >
                      > I don't. I think it sufficient to point out that, among other
                      > important things, std::vector provides access to its bounds and your
                      > class does not. Therefore every client of your class must have a copy
                      > of the array boundaries while with std::vector they would not.
                      > std::vector also does significantly more than your class including
                      > growing in size and providing methods for sorting, searching, etc.
                      > Your class not only doesn't do much, it doesn't do anything. It would
                      > be MUCH more effecient to implement what you are doing with a simple
                      > pointer and some casts.[/color]

                      I've been programming for almost 20 years, and I'm 2nd ranking C++
                      expert in the Experts-Exchange
                      (http://www.experts-exchange.com/Cplusplus)
                      I'm also a frequent contributor to Code-Guru C++/VC++ topic area as
                      well as Code Project Visual C++ and STL topic area.
                      If this is what you consider a newbie, then I guess I'm a newbie.

                      What ever label you choose to give me or others, does not take away
                      from the fact that you're argument is flawed and very incorrect.
                      It's been my experience that debaters that result in name calling do
                      so, because they don't have a legitimate argument to put forth.

                      I believe this is the case here.
                      You've only attempted to side track the real issue with petty
                      critiques that have nothing to do with the main point.

                      [color=blue]
                      > I'll let the FAQ stand on its own. I don't need to defend it and it's
                      > obvious to me now that I am arguing with a pack of newbies that refuse
                      > to learn anything valueable. The FAQ was written by people smarter
                      > and/or more experienced than either of us;[/color]

                      Please speak for yourself. Your level of experience may coincide with
                      the above comment, but I would make no such assumptions with my
                      experience and expertise.
                      Moreover, even the best experts in any field make mistakes.
                      IMHO, this part of the C++ FAQ is incorrect.

                      Comment

                      • roberts.noah@gmail.com

                        #41
                        Re: Two-Dimensional Dynamic Arrays


                        Axter wrote:[color=blue]
                        > roberts.noah@gm ail.com wrote:[color=green]
                        > > Axter wrote:
                        > >[color=darkred]
                        > > > I think you should provide an example as how this simple generic class
                        > > > would be a nightmare to maintain, anymore then using a generic class
                        > > > like std::vector.[/color]
                        > >
                        > > I don't. I think it sufficient to point out that, among other
                        > > important things, std::vector provides access to its bounds and your
                        > > class does not. Therefore every client of your class must have a copy
                        > > of the array boundaries while with std::vector they would not.
                        > > std::vector also does significantly more than your class including
                        > > growing in size and providing methods for sorting, searching, etc.
                        > > Your class not only doesn't do much, it doesn't do anything. It would
                        > > be MUCH more effecient to implement what you are doing with a simple
                        > > pointer and some casts.[/color]
                        >
                        > I've been programming for almost 20 years, and I'm 2nd ranking C++
                        > expert in the Experts-Exchange
                        > (http://www.experts-exchange.com/Cplusplus)
                        > I'm also a frequent contributor to Code-Guru C++/VC++ topic area as
                        > well as Code Project Visual C++ and STL topic area.
                        > If this is what you consider a newbie, then I guess I'm a newbie.[/color]

                        Well, I don't really pay attention to "credential s". I've been
                        published too. BFD. My analysis of your class stands. If you could
                        counter that analysis I guess you would have. Appeal to authority
                        isn't good enough in my book.[color=blue]
                        >
                        > What ever label you choose to give me or others, does not take away
                        > from the fact that you're argument is flawed and very incorrect.
                        > It's been my experience that debaters that result in name calling do
                        > so, because they don't have a legitimate argument to put forth.
                        >
                        > I believe this is the case here.
                        > You've only attempted to side track the real issue with petty
                        > critiques that have nothing to do with the main point.[/color]

                        They actually have everything to do with the main point. Your class
                        design is fundamentally flawed. You offered it as an example of how to
                        implement [][] and the plain fact is that your implementation is broken
                        in ways that are very fundamental and very basic. Your attempt at
                        creating the [][] syntax just to have that syntax led you down a path
                        that resulted in code that had fundamental flaws in it destined to
                        create problems in any decently sized project; my analysis (or
                        critique) of these things speak directly to the issue. I have
                        explained those ways already and you fail to answer to them but instead
                        have decided to claim I sidetracked the issue.

                        Maybe my claim that you're a newbie was a little unwaranted but the
                        class you provided as an example of how to do something right as a
                        counter to the FAQ entry is very newbieish and flawed.

                        Comment

                        • roberts.noah@gmail.com

                          #42
                          Re: Two-Dimensional Dynamic Arrays


                          Gianni Mariani wrote:
                          [color=blue][color=green]
                          > > ... Creating a proxy answers this problem by
                          > > returning an object that just stores X and calls (x,y) on the matrix to
                          > > return the appropriate value. This is totally unnecissary and only
                          > > adds to the complexity of the program without giving any real benefit -[/color]
                          >
                          > (x,y) does not work with legacy code or generic programming. This is a
                          > major issue if you're looking for a general solution.[/color]

                          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<typena me 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...especi ally
                          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[i] 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.

                          Comment

                          • Axter

                            #43
                            Re: Two-Dimensional Dynamic Arrays

                            roberts.noah@gm ail.com wrote:[color=blue]
                            > Gianni Mariani wrote:
                            >[color=green][color=darkred]
                            > > > ... Creating a proxy answers this problem by
                            > > > returning an object that just stores X and calls (x,y) on the matrix to
                            > > > return the appropriate value. This is totally unnecissary and only
                            > > > adds to the complexity of the program without giving any real benefit -[/color]
                            > >
                            > > (x,y) does not work with legacy code or generic programming. This is a
                            > > major issue if you're looking for a general solution.[/color]
                            >
                            > 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.[/color]

                            That is not an artificial requirement, and any experience programmer
                            would tell you that.
                            Legacy code is a very real world, and very common requirement for day
                            to day coding.
                            Often when adding new modifications to legacy code, you're force to use
                            the current interface, which would exclude using operator().
                            It would be a terrible idea to introduce the use of operator() in one
                            part of the source code, and use [][], in another part of the same
                            source code.
                            And changing the entire code to use operator() would more then likely
                            introduce many bugs, that wouldn't get picked up until your customer
                            reports it.
                            It's an equally bad idea to say it's better to use raw pointers, which
                            would also have a high chance of introducing new bugs.
                            It's safer to use a wrapper class, like the one I posted.

                            The main purpose for the wrapper class is to show how to efficiently
                            implement a dynamic 2D array class using [][] interface.
                            I intentionally did not add any extra bounds checking code, because
                            that would have created a distraction from the main implementation I
                            was trying to convey.
                            Any beginner can add GetX and GetY functions to this class:
                            int GetRow() const{return m_row;}
                            int GetCol() const{return m_col;}

                            If you don't know how to do this, then you shouldn't even be looking at
                            this class.


                            [color=blue]
                            > 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 ->[/color]
                            I completely disagree. I've only read contrived justifications for
                            using () syntax, that have nothing to do with generic programming, or
                            with 99.99% of C++ development.
                            Example:
                            Previous Post:[color=blue][color=green][color=darkred]
                            >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>[/color]
                            >>Tell me then, how exactly is the compiler going to hide the internal representiation of
                            >>the matrix when you have exposed it with the first [] operator??!![color=darkred]
                            >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>>>>>>>>>>> >>>>>[/color][/color][/color]

                            99.99% of developers would never ever need to get the internal
                            representation of the matrix, and would never need to change col for
                            row within the matrix.
                            For those very few developers that do need to perform such optimization
                            methods, most likely their implementation will only work efficiently in
                            a particular OS and hardware settings.
                            It would not be generic implementation, that you could port to other OS
                            or even other hardware using the same OS.
                            A developer would have a better chance of winning the lottery, then
                            ever having to use these optimization methods.

                            The justification given in the C++ FAQ and the justification given in
                            this thread, are very weak at best, and play no part in generic C++
                            programming.
                            [color=blue]
                            > 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).[/color]

                            There are many, many reasons to create an object class, and protection
                            is only one of many.
                            The dynamic_2d_arra y class is type safe, and reduces the chance of
                            memory leaks compare to using pointers.
                            Other then using pointers, you can not create a dynamic 2D array using
                            POD concrete types.
                            It's far safer to use the wrapper class.
                            [color=blue]
                            >
                            > 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<typena me 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
                            > [][].[/color]
                            There are so many things wrong with the above class.
                            1. The above class is not safe as it can be since col_num and row_num
                            are not constant. Clearly they should be constant, since there's no
                            implementation for changing the size of the array.

                            2. Your class can not be used if the object is constant, since you
                            failed to provide a constant version for operator().

                            3. Your implementation is returning by value, which makes it very
                            inefficient.

                            4. The class also fails to test that the input pointer is not NULL.
                            (should have assertion).

                            5. Since your class is taking int instead of size_t, your class can
                            also fail if the input arguments are negative. CArrAdapter
                            MyBadArrAdapter (NULL, -3, -99);

                            6. MyBadArrAdapter (-4, -123);//Your if condition would not pick this
                            up, and would not throw

                            7. I also find very little value in this class, since it does not do
                            any clean up work, and therefore you would most likely end up with
                            memory leaks. It would be just as bad as using raw pointers.

                            Anyone using this type of class in a real world requirement, would end
                            up with memory leaks, poor performance, and a maintenance nightmare.

                            Comment

                            • Gianni Mariani

                              #44
                              Re: Two-Dimensional Dynamic Arrays

                              roberts.noah@gm ail.com wrote:[color=blue]
                              > Gianni Mariani wrote:
                              >
                              >[color=green][color=darkred]
                              >>>... Creating a proxy answers this problem by
                              >>>returning an object that just stores X and calls (x,y) on the matrix to
                              >>>return the appropriate value. This is totally unnecissary and only
                              >>>adds to the complexity of the program without giving any real benefit -[/color]
                              >>
                              >>(x,y) does not work with legacy code or generic programming. This is a
                              >>major issue if you're looking for a general solution.[/color]
                              >
                              >
                              > 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.[/color]

                              Stop.

                              You have 2 options, a) makes for hard work, b) means less work. The
                              result is identical from a performance prespective. You insist on
                              option a).

                              Enough said.

                              Comment

                              • Axter

                                #45
                                Re: Two-Dimensional Dynamic Arrays


                                roberts.noah@gm ail.com wrote:[color=blue]
                                > Gianni Mariani wrote:
                                >[color=green][color=darkred]
                                > > > ... Creating a proxy answers this problem by
                                > > > returning an object that just stores X and calls (x,y) on the matrix to
                                > > > return the appropriate value. This is totally unnecissary and only
                                > > > adds to the complexity of the program without giving any real benefit -[/color]
                                > >
                                > > (x,y) does not work with legacy code or generic programming. This is a
                                > > major issue if you're looking for a general solution.[/color]
                                >
                                > 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<typena me 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
                                > [][].[/color]

                                I forgot to mention that your wrapper class also fails to have a GetCol
                                and GetRow function.

                                For better advise on this subject, check out the following CodeGuru STL
                                FAQs:


                                The above STL FAQ has a wrapper class for a 2D array, which uses
                                vector<vector<T > >.
                                It has a resize function that allows the size to change after object
                                construction.
                                It would be safer to use this type of implementation, and it would be
                                eaiser to interface your code with STL objects.

                                The CodeGuru FAQ author also originally promoted the operator() method,
                                and after much debate, he changed the FAQ to promote [][] instead.

                                The CodeGuru site is a well known respected site, that has members that
                                are much better at responding to critiques then the author of the C++
                                FAQ.

                                Also check out another CodeGuru STL FAQ:


                                The above link has two classes. One which I'm the author of, and the
                                second class which allows you to use both [][] and operator() method.
                                I don't think it's a good idea to have both methods in a class, but
                                some developers may find this method more acceptable.

                                Comment

                                Working...