comp.lang.ada
 help / color / mirror / Atom feed
* C++ STL Components and Ada
@ 2001-07-16  0:37 James Rogers
  2001-07-17  4:26 ` Brian Rogoff
  0 siblings, 1 reply; 9+ messages in thread
From: James Rogers @ 2001-07-16  0:37 UTC (permalink / raw)


Occasionally I read questions from Ada newbies about the presence of
Ada equivalents to the C++ STL. 

After many years of reading about and hearing from C++ programmers that
the STL is the best thing since the invention of fire, I decided to
look into exactly what the STL is. Ok, I took a little longer than 
others :-).

I started by looking at the definition of the C++ Vector class, which
has an analog in Java. I have come to the conclusion that the Vector
class is one of the most used components from the STL. I am aware that
C++ needed some standard kind of "safe" array. The array type
inherited from C certainly does not fit this description. I found the
Vector class to be very flexible, if not overly safe. It does prevent
reading beyond the end of the Vector object. It does not prevent
writing beyond the end of the Vector object because the Vector is
an extensible structure.

In the best case a Vector is about as efficient as an Ada array.
In the worst case it is far less efficient. I cannot imagine using
a Vector in an embedded application with limited memory. I do think
that most C++ code, like most Java code, is not written in the
embedded domain. Therefore, the inefficiencies may not often be
visible.

I have learned a lot about the Vector class by creating an Ada
implementation. The implementation works. It is not particularly
pretty. I suspect it can be improved.

The following code is my generic Vector in Ada.

-- File: Tagged_Vector.ads
--
-- Generic vector for tagged types following C++ rules

generic
	type Element_Type is tagged private;
	with function ">=" (Left, Right : Element_Type) return Boolean;
package Tagged_Vector is
   type Group is array(Positive range <>) of Element_Type;
	type Vector is private;
	function First(Item : in Vector) return Natural;
	function Last(Item : in Vector) return Natural;
	function Size(Item : in Vector) return Natural;
	function Capacity(Item : in Vector) return Natural;
	function Is_Empty(Item : in Vector) return Boolean;
	function Element(Num : in Positive; 
	                 Item : in Vector) return Element_Type;
	procedure Reserve(Num_Items : in Positive;
	                  Item : in out Vector);
	function Front(Item : in Vector) return Element_Type;
	function Back(Item : in Vector) return Element_Type;
	procedure Push_Back(Value : in Element_Type;
	                    Onto  : in out Vector);
	procedure Pop_Back(Value : out Element_Type;
	                   From  : in out Vector);
	procedure Insert(Value  : in Element_Type;
	                 Before : in Positive;
			Onto   : in out Vector);
	procedure Insert(Value      : in Element_Type;
	                 Num_Copies : in Positive;
			Before     : in Positive;
			Onto       : in out Vector);
	procedure Insert(The_Group : in Group;
	                 Before    : in Positive;
			 Onto      : in out Vector);
	procedure Erase(Index : in Positive;
	                From  : in out Vector);
	procedure Erase(First : in Positive;
	                Last  : in Positive;
			From  : in out Vector);
	procedure Resize(Num  : in Positive;
	                 Item : in out Vector);
	function "="(Left, Right : Vector) return Boolean;
	function "<"(Left, Right : Vector) return Boolean;
	
	Vector_Empty_Error : Exception;
private
   type Group_Access is access all Group;
   type Vector is record
	Buffer : Group_Access := new Group(1..20);
	Num_Elements : Natural := 0;
   end record;
end Tagged_Vector; 


-- File : Tagged_Vector.adb
   with Ada.Unchecked_Deallocation;

   package body Tagged_Vector is
      procedure Free is new Ada.Unchecked_Deallocation(
                        Object => Group,
                        Name =>Group_Access);
   
      function First(Item : in Vector) return Natural is
      begin
         if Item.Num_Elements > 0 then
            return 1;
         else
            return 0;
         end if;
      end First;
   
      function Last(Item : in Vector) return Natural is
      begin
         return Item.Num_Elements;
      end Last;
   
      function Size(Item : in Vector) return Natural is
      begin
         return Item.Num_Elements;
      end Size;
   
      function Capacity(Item : in Vector) return Natural is
      begin
         if Item.Buffer /= null then
            return Item.Buffer.all'Last;
         else
            return 0;
         end if;
      end Capacity;
   
      function Is_Empty(Item : in Vector) return Boolean is
      begin
         return Item.Num_Elements = 0;
      end Is_Empty;
   
      function Element(Num : in Positive;
                       Item : in Vector) return Element_Type is
      begin
         if Num <= Item.Num_Elements then
            return Item.Buffer.all(Num);
         else
            return Item.Buffer.all(Item.Num_Elements);
         end if;
      end Element;
   
      procedure Reserve(Num_Items : in Positive;
                        Item : in out Vector) is
         Temp : Group_Access;
      begin
         if Num_Items > Item.Buffer.all'Last then
            Temp := new Group(1..(2 * Num_Items));
         -- Copy Elements to new buffer
            Temp.all(1..Item.Num_Elements) :=
                    Item.Buffer.all(1..Item.Num_Elements);
            Free(Item.Buffer);
         end if;
         Item.Buffer := Temp;
      end Reserve;
   
      function Front(Item : in Vector) return Element_Type is
      begin
         if Item.Num_Elements = 0 then
            raise Vector_Empty_Error;
         end if;
         return Item.Buffer.all(1);
      end Front;
   
      function Back(Item : in Vector) return Element_Type is
      begin
         if Item.Num_Elements = 0 then
            raise Vector_Empty_Error;
         end if;
         return Item.Buffer.all(Item.Num_Elements);
      end Back;
   
      procedure Push_Back(Value : in Element_Type;
                          Onto  : in out Vector) is
         Temp : Group_Access;
      begin
         if Onto.Num_Elements = Onto.Buffer.All'Last then
            Temp := new Group(1..(2 * Onto.Num_Elements));
            Temp.all(1..Onto.Num_Elements) :=
                   Onto.Buffer.all(1..Onto.Num_Elements);
            Free(Onto.Buffer);
            Onto.Buffer := Temp;
         end if;
         Onto.Num_Elements := Onto.Num_Elements + 1;
         Onto.Buffer.all(Onto.Num_Elements) := Value;
      end Push_Back;
   
      procedure Pop_Back(Value : out Element_Type;
                         From  : in out Vector) is
      begin
         if From.Num_Elements = 0 then
            raise Vector_Empty_Error;
         end if;
         Value := From.Buffer.all(From.Num_Elements);
         From.Num_Elements := From.Num_Elements - 1;
      end Pop_Back;
   
      procedure Insert(Value : in Element_Type;
                       Before : in Positive;
                       Onto   : in out Vector) is
         Temp : Group_Access;
         new_Pos : Positive;
      begin
         if Onto.Num_Elements = Onto.Buffer.All'Last then
            Temp := new Group(1..(2 * Onto.Num_Elements));
            Temp.all(1..Onto.Num_Elements) := 
                Onto.Buffer.all(1..Onto.Num_elements);
            Free(Onto.Buffer);
            Onto.Buffer := Temp;
         end if;
         if Before <= Onto.Num_Elements then
            for num in reverse Before..Onto.Num_Elements loop
               Onto.Buffer.all(Num + 1) := Onto.Buffer.All(Num);
            end loop;
            New_Pos := Before;
         else
            New_Pos := Onto.Num_Elements + 1;
         end if;
         Onto.Buffer.All(New_Pos) := Value;
         Onto.Num_Elements := Onto.Num_Elements + 1;
      end Insert;
   
      procedure Insert(Value      : in Element_Type;
                       Num_Copies : in Positive;
                       Before     : in Positive;
                       Onto       : in out Vector) is
      begin
         for copy in 1..Num_Copies loop
            Insert(Value => Value, Before => Before, Onto => Onto);
         end loop;
      end Insert;
   
      procedure Insert(The_Group : in Group;
                       Before    : in Positive;
                       Onto      : in out Vector) is
      begin
         for Index in reverse The_Group'Range loop
            Insert(Value  => The_Group(Index),
                   Before => Before,
                   Onto   => Onto);
         end loop;
      end Insert;
   
      procedure Erase(Index : in Positive;
                      From  : in out Vector) is
      begin
         if Index <= From.Num_Elements then
            for num in Index + 1..From.Num_Elements loop
               From.Buffer.all(Num - 1) := From.Buffer.all(Num);
            end loop;
            From.Num_Elements := From.Num_Elements - 1;
         end if;
      end Erase;
   
      procedure Erase(First : in Positive;
                      Last  : in Positive;
                      From  : in out Vector) is
         Final : Positive;
      begin
         if Last >= First then
            if Last > From.Num_Elements then
               Final := From.Num_Elements;
            else
               Final := Last;
            end if;
            for num in First..Final loop
               Erase(Index => First, From => From);
            end loop;
         end if;
      end Erase;
   
      procedure Resize(Num : in Positive;
                       Item : in out Vector) is
         Temp : Group_Access;
      begin
         if Num >= (2 * Item.Num_Elements) then
            Temp := new Group(1..Num);
            for index in 1..Item.Num_Elements loop
               Temp.all(index) := Item.Buffer.all(Index);
            end loop;
            Free(Item.Buffer);
            Item.Buffer := Temp;
         end if;
      end Resize;
   
      function "="(Left, Right : in Vector) return Boolean is
         Result : Boolean;
      begin
         if Left.Num_Elements = Right.Num_Elements then
            Result := True;
            for index in 1..Left.Num_Elements loop
               if Left.Buffer.all(index) /= Right.Buffer.all(Index) then
                  Result := False;
               end if;
               exit when Result = False;
            end loop;
         else
            Result := False;
         end if;
         return Result;
      end "=";
   
      function "<"(Left, Right : in Vector) return Boolean is
         Result : Boolean;
      begin
         if Left.Num_Elements <= Right.Num_Elements then
            Result := True;
            for index in 1..Left.Num_Elements loop
               if Left.Buffer.all(Index) >= Right.Buffer.all(Index) then
                  Result := False;
               end if;
               exit when Result = False;
            end loop;
         else
            Result := False;
         end if;
         return Result;
      end "<";
   end Tagged_Vector;

Jim Rogers
Coloardo Springs, Colorado USA



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-16  0:37 C++ STL Components and Ada James Rogers
@ 2001-07-17  4:26 ` Brian Rogoff
  2001-07-17 14:48   ` James Rogers
  0 siblings, 1 reply; 9+ messages in thread
From: Brian Rogoff @ 2001-07-17  4:26 UTC (permalink / raw)


On Mon, 16 Jul 2001, James Rogers wrote:
> Occasionally I read questions from Ada newbies about the presence of
> Ada equivalents to the C++ STL. 
> 
> After many years of reading about and hearing from C++ programmers that
> the STL is the best thing since the invention of fire, I decided to
> look into exactly what the STL is. Ok, I took a little longer than 
> others :-).

The important thing you seem to be missing in your post is the presence of 
an ancillary type called iterators which are defined over the containers
and abstract the traversal so that algorithms are decoupled from
containers. You can do this in Ada too, but it's notationally a bit nicer
in C++ since the iterators over the commonest sequences map directly to
pointers.

I wouldn't say they're the best thing since the invention of fire, but C++
templates allow all sorts of interesting things, almost like macros, but
linked with the type system. They provide a crude form of parametric
polymorphism which doesn't have the overhead associated with typical
implementations of polymorphic languages. I can easily imagine an Ada-like
language which steals some nice aspects of C++ templates. 

-- Brian





^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-17  4:26 ` Brian Rogoff
@ 2001-07-17 14:48   ` James Rogers
  2001-07-17 19:47     ` Jon Orris
  2001-07-19 20:48     ` Ray Blaak
  0 siblings, 2 replies; 9+ messages in thread
From: James Rogers @ 2001-07-17 14:48 UTC (permalink / raw)


Brian Rogoff wrote:
> 
> On Mon, 16 Jul 2001, James Rogers wrote:
> > Occasionally I read questions from Ada newbies about the presence of
> > Ada equivalents to the C++ STL.
> >
> > After many years of reading about and hearing from C++ programmers that
> > the STL is the best thing since the invention of fire, I decided to
> > look into exactly what the STL is. Ok, I took a little longer than
> > others :-).
> 
> The important thing you seem to be missing in your post is the presence of
> an ancillary type called iterators which are defined over the containers
> and abstract the traversal so that algorithms are decoupled from
> containers. You can do this in Ada too, but it's notationally a bit nicer
> in C++ since the iterators over the commonest sequences map directly to
> pointers.

I considered the issue of iterators for this example. C++ actually uses
pointers for iterators on a Vector. This works for C++ because
internally the C++ vector uses the C-style array. C-style arrays do
are, in many aspects, indistinguishable from arrays.

Ada does not suffer the C confusion between arrays and pointers,
or access types. I chose to use the index number (subtype Positive)
as the iterator. The implementation takes this into accoount.
For instance, refrence to an index outside the range of the internal
array is cleanly handled.

Using subtype Positive for the iterator still satisfies the definition
of a Vector. Addition to the end is constant time (as long as a new
allocation is not required). Insertion to the middle is linear time
O(n) as long as a new allocation is not require. Insertion or 
removal of Vector elements causes previous iterator values to become
unstable. That is, they no longer refer to the same Vector elements.

> I wouldn't say they're the best thing since the invention of fire, but C++
> templates allow all sorts of interesting things, almost like macros, but
> linked with the type system. They provide a crude form of parametric
> polymorphism which doesn't have the overhead associated with typical
> implementations of polymorphic languages. I can easily imagine an Ada-like
> language which steals some nice aspects of C++ templates.
> 

C++ templates also have the disadvantage that their instantiations
cannot
be checked by the compiler. Instead, you must deal with runtime errors
when making simple mistakes such as filling a container with values
of Animal and then trying to read them out as values of Mineral.

I find it ineresting that Java, in its current work to implement a
generic programming capability has rejected the C++ template model.
Instead it has adopted a model very similar to the Ada generic 
model, where instantiation is performed at comile time. The reasons
given for this are stronger type safety and better compatibility with
existing Java Virtual Machines. This model allows the Virtual Machines
to be entirely ignorant of generics. All they see is normal byte
code for fully instantiated classes.

I wondered just where the Ada influence on Java generics came from
until I read a list of contributors to the Java generic design. The 
name Norman Cohen of IBM stood out. Among other things, Norman Cohen
is the author of my favorite Ada text "Ada as a Second Language".

I do not claim that C++ templates are evil. I do claim that they 
are not clearly superior to Ada generics. Each approach has its own
set of strengths and weaknesses.

Jim Rogers
Colorado Springs, Colorado USA



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-17 14:48   ` James Rogers
@ 2001-07-17 19:47     ` Jon Orris
  2001-07-18  3:09       ` James Rogers
  2001-07-19 20:48     ` Ray Blaak
  1 sibling, 1 reply; 9+ messages in thread
From: Jon Orris @ 2001-07-17 19:47 UTC (permalink / raw)


"James Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
news:3B5450EF.7D82CCF5@worldnet.att.net...
> Brian Rogoff wrote:
> > I wouldn't say they're the best thing since the invention of fire, but
C++
> > templates allow all sorts of interesting things, almost like macros, but
> > linked with the type system. They provide a crude form of parametric
> > polymorphism which doesn't have the overhead associated with typical
> > implementations of polymorphic languages. I can easily imagine an
Ada-like
> > language which steals some nice aspects of C++ templates.
> >
>
> C++ templates also have the disadvantage that their instantiations
> cannot
> be checked by the compiler. Instead, you must deal with runtime errors
> when making simple mistakes such as filling a container with values
> of Animal and then trying to read them out as values of Mineral.

Could you provide an example of what you mean here? I've seen this claim
before, and have been unable to think of how this would occur. I've never
had this sort of issue crop up when developing in C++.

Jon Orris
jonorris@ieee.org






^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-17 19:47     ` Jon Orris
@ 2001-07-18  3:09       ` James Rogers
  2001-07-18 15:48         ` Matthias Benkmann
  2001-07-18 18:00         ` Jon Orris
  0 siblings, 2 replies; 9+ messages in thread
From: James Rogers @ 2001-07-18  3:09 UTC (permalink / raw)


Jon Orris wrote:
> 
> "James Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
> news:3B5450EF.7D82CCF5@worldnet.att.net...
>> > C++ templates also have the disadvantage that their instantiations
> > cannot
> > be checked by the compiler. Instead, you must deal with runtime errors
> > when making simple mistakes such as filling a container with values
> > of Animal and then trying to read them out as values of Mineral.
> 
> Could you provide an example of what you mean here? I've seen this claim
> before, and have been unable to think of how this would occur. I've never
> had this sort of issue crop up when developing in C++.
> 

Sure.

All pointers to Objects in C++ are equivalent to class-wide access
values in Ada. A pointer to an object can point to objects of all
classes inheriting from the pointer's object base type.

When instantiating a template you must specify the class of the
objects to be contained by the generic container class. That
class parameter allows objects of the class and all its 
subclasses to be stored in the container class. So far, so good.

Now, what happens if you instantiate the C++ Vector class with
class Airplane, followed by appropriate additions of Airplane
objects to the container. However, you used the cut and paste
method of programming, so one of your functions extracts data
from the Vector and wants to assign it to a reference to the
String class.

Your compiler is completely satisfied with this situation.
The compiler does not check actual parameter types for template
instantiation. All that is done at run time. When you test the
program you find that you have some problems. If you are really
lucky someone has programmed some exceptions into your code and
the code dies cleanly and quickly. If you are unlucky, you must
try to figure out where the data is getting corrupted, and how
to fix it. This usually involves some non-trivial effort running
a debugger. Even worse, the offending code is in a branch not
normally encountered in your code. It doesn't get tested in house.
However, the customers do encounter that branch. Now you have a
relatively expensive problem. You must first recreate the reported
problem. Then you must analyze the cause, and finally fix
the problem. Release of the fix may have to wait until the next
scheduled software release for this product, meaning that your
code will have a possibly serious problem, in customer hands,
for an extended period of time.

Compare this with the Ada generic instantiation. The compiler
checks the actual parameters against the generic formal parameters.
It also can then check all the return values from functions, and
return types from procedure parameter lists. If there is an error
it will be detected BEFORE you can run your program. You do not
need to rely on testing to find the problems. You do not run the
risk that customers will encounter the problem. You do not
incur the costs of re-releasing the code to provide a fix for the
problem.

Jim Rogers
Colorado Springs, Colorado USA



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-18  3:09       ` James Rogers
@ 2001-07-18 15:48         ` Matthias Benkmann
  2001-07-18 18:00         ` Jon Orris
  1 sibling, 0 replies; 9+ messages in thread
From: Matthias Benkmann @ 2001-07-18 15:48 UTC (permalink / raw)


On Wed, 18 Jul 2001 03:09:25 GMT, James Rogers
<jimmaureenrogers@worldnet.att.net> wrote:

>Jon Orris wrote:
>> 
>> "James Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
>> news:3B5450EF.7D82CCF5@worldnet.att.net...
>>> > C++ templates also have the disadvantage that their instantiations
>> > cannot
>> > be checked by the compiler. Instead, you must deal with runtime errors
>> > when making simple mistakes such as filling a container with values
>> > of Animal and then trying to read them out as values of Mineral.
>> 
>> Could you provide an example of what you mean here? I've seen this claim
>> before, and have been unable to think of how this would occur. I've never
>> had this sort of issue crop up when developing in C++.
>> 
>
>Sure.
>
>All pointers to Objects in C++ are equivalent to class-wide access
>values in Ada. A pointer to an object can point to objects of all
>classes inheriting from the pointer's object base type.
>When instantiating a template you must specify the class of the
>objects to be contained by the generic container class. That
>class parameter allows objects of the class and all its 
>subclasses to be stored in the container class. So far, so good.
>
>Now, what happens if you instantiate the C++ Vector class with
>class Airplane, followed by appropriate additions of Airplane
>objects to the container. However, you used the cut and paste
>method of programming, so one of your functions extracts data
>from the Vector and wants to assign it to a reference to the
>String class.
>
>Your compiler is completely satisfied with this situation.

Nope.

>The compiler does not check actual parameter types for template
>instantiation. All that is done at run time. 

This is just plain wrong. I dare you to post some code to support your
claim. Look at this:

#include <vector>

using namespace std;

class airplane
{
};

class notAnAirplane
{
};

int main()
{
  vector<airplane> va;
  airplane a;
  va.insert(va.begin(),a);  //OK! insert an airplane

  notAnAirplane na;
  va.insert(va.begin(),na); //NOT OK! na is not an airplane

  /*now try to circumvent type-safety by using pointers*/
  vector<airplane*> va2; //a vector of pointer to airplane
  va2.insert(va2.begin(),&a); //OK! &a is pointer to airplane a

/*NOT OK! &na is pointer to notAnAirplane na*/
  va2.insert(va2.begin(),&na); 
};


Ty to find a C++ compiler that will chew it. You won't! Both lines
where you try to insert notAnAirplane or pointer to notAnAirplane into
a vector of airplane or pointer to airplane give compiler errors.
Templates are purely a compile time thing and type checking is static.
In Java however, vector only carries Objects and the above would work
because there is only vector<Object> in Java (although not with this
syntax). You have definitely mixed up the 2 languages.


>Compare this with the Ada generic instantiation. The compiler
>checks the actual parameters against the generic formal parameters.
>It also can then check all the return values from functions, and
>return types from procedure parameter lists. If there is an error
>it will be detected BEFORE you can run your program. You do not
>need to rely on testing to find the problems. You do not run the
>risk that customers will encounter the problem. You do not
>incur the costs of re-releasing the code to provide a fix for the
>problem.

Same thing for C++.  That is why templates are such a Good Thing.

MSB

----
By the way:
Vacuum cleaners suck!



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-18  3:09       ` James Rogers
  2001-07-18 15:48         ` Matthias Benkmann
@ 2001-07-18 18:00         ` Jon Orris
  1 sibling, 0 replies; 9+ messages in thread
From: Jon Orris @ 2001-07-18 18:00 UTC (permalink / raw)


"James Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
news:3B54FE7B.9EDF993C@worldnet.att.net...
> Jon Orris wrote:
> >
> > "James Rogers" <jimmaureenrogers@worldnet.att.net> wrote in message
> > news:3B5450EF.7D82CCF5@worldnet.att.net...
> >> > C++ templates also have the disadvantage that their instantiations
> > > cannot
> > > be checked by the compiler. Instead, you must deal with runtime errors
> > > when making simple mistakes such as filling a container with values
> > > of Animal and then trying to read them out as values of Mineral.
> >
> > Could you provide an example of what you mean here? I've seen this claim
> > before, and have been unable to think of how this would occur. I've
never
> > had this sort of issue crop up when developing in C++.
> >
>
> Sure.
>
> All pointers to Objects in C++ are equivalent to class-wide access
> values in Ada. A pointer to an object can point to objects of all
> classes inheriting from the pointer's object base type.
>
> When instantiating a template you must specify the class of the
> objects to be contained by the generic container class. That
> class parameter allows objects of the class and all its
> subclasses to be stored in the container class. So far, so good.
>
> Now, what happens if you instantiate the C++ Vector class with
> class Airplane, followed by appropriate additions of Airplane
> objects to the container. However, you used the cut and paste
> method of programming, so one of your functions extracts data
> from the Vector and wants to assign it to a reference to the
> String class.

This isn't so, unless I'm completely misunderstanding your point. One
of the nice things about C++ templates is that they lead to greater type
safety. When using C++,  many template programming techniques can
get you closer to the degree of type safety offered by Ada.

In the following sample, assignString and noSuchMethod fail to compile
when instantiated.

class Airplane
{
public:
 Airplane(const char* name) : m_name(name)
 {
 }

 const std::string& GetName() const
 {
  return m_name;
 }

private:
 std::string m_name;
};

template<class T>
void works(const std::vector<T*>& vec)
{
 for(std::vector<T*>::const_iterator iter = vec.begin(); iter != vec.end();
++iter)
 {
  T* val = *iter;
  std::cout << val->GetName() << std::endl;
 }
}

template<class T>
void assignString(const std::vector<T*>& vec)
{
 for(std::vector<T*>::const_iterator iter = vec.begin(); iter != vec.end();
++iter)
 {
  std::string& foo = *iter;
 }
}

template<class T>
void noSuchMethod(const std::vector<T*>& vec)
{
 for(std::vector<T*>::const_iterator iter = vec.begin(); iter != vec.end();
++iter)
 {
  T* val = *iter;
  std::cout << val->DoSomething() << std::endl;
 }
}

int main()
{
 std::vector<Airplane*> planes;
 // Yes, this leaks memory.
 planes.push_back(new Airplane("first"));
 planes.push_back(new Airplane("second"));

 works( planes );
 assignString( planes );
 noSuchMethod( planes );

 return 0;
}

C:\dev\test>g++ foo.cpp
foo.cpp: In function `void assignString<Airplane>(const vector<Airplane *,
allocator<Airplane *> > &)':
foo.cpp:57:   instantiated from here
foo.cpp:36: conversion from `Airplane *const' to non-scalar type
`basic_string<char,string_char_traits<char>,
__default_alloc_template<false,0> >' requested
foo.cpp:36: cannot initialize `basic_string<char,string_char_traits<char>,
__default_alloc_template<false,0> > &' from `Airplane *const'
foo.cpp: In function `void noSuchMethod<Airplane>(const vector<Airplane *,
allocator<Airplane *> > &)':
foo.cpp:58:   instantiated from here
foo.cpp:46: no matching function for call to `Airplane::DoSomething ()'

> Your compiler is completely satisfied with this situation.
> The compiler does not check actual parameter types for template
> instantiation. All that is done at run time. When you test the
> program you find that you have some problems.

The compiler always checks parameter types at instantiation.

One thing that is a problem with C++ templates is that there are certain
bugs that won't show up until a template is instantiated, I.e.

template<class T>
void insane(const std::vector<T*>& vec)
{
 Airplane a = 17;
}
// compiles with insane call commented out.
int main()
{
 std::vector<Airplane*> planes;
 // insane( planes );
}

I'm still learning Ada, and am not very familiar with generics,
so hopefully this is something that Ada would fail to compile altogether.

Bwt, lest I give the wrong impression, I'm quite aware of the shortcomings
in C++,
and the STL. At my prior job, we avoided much of the STL, originally because
it
wasn't standardized and/or supported on all compilers, then because our in
house
container library was substantially safer. You had to be actively stupid to
cause problems
with it.

Even with my limited knowledge of Ada, I can see substantial advantages over
C++.
I used to play a 'game' of C++ vs. Ada. After several hours of tracking down
a hideous
defect in some departed engineer's code, I'd ask myself: "Would Ada's
compile or run
time checks have detected this automatically?" 9 out of 10 times, the answer
was YES.

Jon Orris
jonorris@ieee.org






^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-17 14:48   ` James Rogers
  2001-07-17 19:47     ` Jon Orris
@ 2001-07-19 20:48     ` Ray Blaak
  2001-07-20  0:40       ` Brian Rogoff
  1 sibling, 1 reply; 9+ messages in thread
From: Ray Blaak @ 2001-07-19 20:48 UTC (permalink / raw)


James Rogers <jimmaureenrogers@worldnet.att.net> writes:
> I find it ineresting that Java, in its current work to implement a
> generic programming capability has rejected the C++ template model.
> Instead it has adopted a model very similar to the Ada generic 
> model, where instantiation is performed at comile time. The reasons
> given for this are stronger type safety and better compatibility with
> existing Java Virtual Machines. This model allows the Virtual Machines
> to be entirely ignorant of generics. All they see is normal byte
> code for fully instantiated classes.

Do you have some URLs for discussions of Java generics? I found a slide show
at java.sun.com, but could not get it due to password problems.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
blaak@infomatch.com                            The Rhythm has my soul.



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: C++ STL Components and Ada
  2001-07-19 20:48     ` Ray Blaak
@ 2001-07-20  0:40       ` Brian Rogoff
  0 siblings, 0 replies; 9+ messages in thread
From: Brian Rogoff @ 2001-07-20  0:40 UTC (permalink / raw)


On 19 Jul 2001, Ray Blaak wrote:
> Do you have some URLs for discussions of Java generics? I found a slide show
> at java.sun.com, but could not get it due to password problems.

http://www.cs.bell-labs.com/who/wadler/pizza/gj/

and from there to 

http://www.cs.bell-labs.com/who/wadler/pizza/gj/Documents/index.html

-- Brian





^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2001-07-20  0:40 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-07-16  0:37 C++ STL Components and Ada James Rogers
2001-07-17  4:26 ` Brian Rogoff
2001-07-17 14:48   ` James Rogers
2001-07-17 19:47     ` Jon Orris
2001-07-18  3:09       ` James Rogers
2001-07-18 15:48         ` Matthias Benkmann
2001-07-18 18:00         ` Jon Orris
2001-07-19 20:48     ` Ray Blaak
2001-07-20  0:40       ` Brian Rogoff

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox