From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,1fa85f3df5841ae1 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news4.google.com!news.glorb.com!border1.nntp.dca.giganews.com!border2.nntp.dca.giganews.com!nntp.giganews.com!elnk-atl-nf1!newsfeed.earthlink.net!stamper.news.atl.earthlink.net!newsread1.news.atl.earthlink.net.POSTED!14bb18d8!not-for-mail Sender: mheaney@MHEANEYX200 Newsgroups: comp.lang.ada Subject: Re: Ada.Containers.Vectors - querying multiple elements References: <426e4c2b$0$7515$9b4e6d93@newsread2.arcor-online.net> From: Matthew Heaney Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Date: Thu, 28 Apr 2005 13:18:42 GMT NNTP-Posting-Host: 24.149.57.125 X-Complaints-To: abuse@earthlink.net X-Trace: newsread1.news.atl.earthlink.net 1114694322 24.149.57.125 (Thu, 28 Apr 2005 06:18:42 PDT) NNTP-Posting-Date: Thu, 28 Apr 2005 06:18:42 PDT Organization: EarthLink Inc. -- http://www.EarthLink.net Xref: g2news1.google.com comp.lang.ada:10780 Date: 2005-04-28T13:18:42+00:00 List-Id: Duncan Sands writes: > When you have a container that is an extensible array, wanting to be > able to directly access slices of it as an array seems normal (and > useful) to me. In the STL way of doing things, you don't write algorithms in terms of a specific container. You write algorithms in terms of an "abstract container." Iterators allow you to view a container in a container-neutral way, as merely a "sequence of items," described using an iterator pair to bound the sequence, and with iterator operations for navigating among the elements of the sequence. What people sometims forget is that the STL is really an algorithms library. The containers are designed to allow you to apply an algorithm over the elements. The nice thing about the STL is that it treats all containers, including built-in arrays, the same. Actually, I said that kinda backwards. The STL treats all containers just like built-in arrays. This is because the STL follows the C machine model, in which items exist at addresses, and to view an item you deference a pointer with that address as its value. The problem you're having is that you have an algorithm written in terms of a specific container: an array. And now you want to apply that algorithm to a different kind of container: a vector. This is precisely the kind of problem the STL algorithm model was designed to solve. You can do this in Ada too, by writing algorithms in a way that is container neutral. See for example generic_anonymous_array_sort, which is declared like this: generic type Index_Type is (<>); with function Less (Left, Right : Index_Type) return Boolean is <>; with procedure Swap (Left, Right : Index_Type) is <>; procedure Generic_Anonymous_Array_Sort (First, Last : in Index_Type'Base); Now this is named "anonymous array sort," but in fact it works over any container (hint: vector) that supports indexing with a discrete index type. The generic formal subprogram Less compares two items in the "array", and Swap exchanges them. Had you written your algorithm as above, then you wouldn't be having the difficulties you're having now. It would work for an array: procedure Op (A : in out Array_Type) is function Less (L, R : IT) return Boolean is begin return A (L) < A (R); end; procedure Swap (L, R : IT) is LE : constant ET := A (L); begin A (L) := A (R); A (R) := LE; end; procedure Sort is new Generic_Anonymous_Array_Sort (IT); begin Sort (A'First, A'Last); end; You'll note carefully that we don't pass the array type to the instantiation. That's why the algorithm is "container neutral." The algorithm above would work equally well for a vector: procedure Op (V : in out Vector) is function Less (L, R : IT) return Boolean is begin return V.Element (L) < V.Element (R); end; procedure Swap (L, R : IT) is LE : constant ET := V.Element (L); begin V.Replace_Element (L, V.Element (R)); V.Replace_Element (R, LE); end; procedure Sort is new Generic_Anonymous_Array_Sort (IT); begin Sort (First_Index (V), Last_Index (V)); end; You could even write an array-specific, or vector-specific algorithm, in terms of the non-specific algorithm, so you'd only have to write those little binder operations once: generic type IT is (<>); type ET is private; type Array_Type is array (IT range <>) of ET; procedure Generic_Array_Sort (A : in out Array_Type); procedure Generic_Array_Sort (A : in out Array_Type) is function Less (L, R : IT) return Boolean is begin return A (L) < A (R); end; procedure Swap (L, R : IT) is LE : constant ET := A (L); begin A (L) := A (R); A (R) := LE; end; procedure Sort is new Generic_Anonymous_Array_Sort (IT); begin Sort (A'First, A'Last); end Generic_Array_Sort; For the vector, you could say: generic with package Vector_Types is new Ada.Containers.Vectors (<>); procedure Generic_Vector_Sort (V : in out Vector); Or you could say: generic type IT is (<>); type ET (<>) is private; type VT (<>) is limited private; with function Element (V : VT; I : IT) return ET is <>; with proc Repl_Elem (V : VT; I : IT; E : ET) is <>; procedure Generic_Vector_Sort (V : in out VT); Now, don't you think that's better than what you did? > I guess the point is that Vector is not an extensible array - the > designers chose a more abstract design. An extensible array is the model for a vector, but of course a vector doesn't have to be implemented that way. You want to view the elements in a vector as a contiguous array, but that wouldn't confere any benefits unless if the underlying implementation is a contiguous array.