comp.lang.ada
 help / color / mirror / Atom feed
* Converting C++ class to Ada
@ 1996-12-10  0:00 Ken Garlington
  1996-12-11  0:00 ` Norman H. Cohen
                   ` (4 more replies)
  0 siblings, 5 replies; 22+ messages in thread
From: Ken Garlington @ 1996-12-10  0:00 UTC (permalink / raw)



In an attempt to better understand both C++ and Ada, I've been
converting some C++ code into Ada. I'm struggling with this particular
class:

  class CTableXY
  {
  public:
    CMotor&   XMotor;
    CMotor&   YMotor;
    CSwitch&  XLimit;
    CSwitch&  YLimit;
    CTableXY( CMotor& xmotor, CMotor& ymotor,
       CSwitch& xlim, CSwitch& ylim ) :
       XMotor(xmotor), YMotor(ymotor),
       XLimit(xlim), YLimit(ylim) {}
    void SetVelocityX( float vel )
    { XMotor.SetSpeed( vel ); }
    void SetVelocityY( float vel )
    { YMotor.SetSpeed( vel ); }
    int GetSwitchX( void ) { return
      XLimit.isOpen(); }
    int GetSwitchY( void ) { return
      YLimit.isOpen(); }
  };

It seems to me that the straightforward Ada translation is something
like:

  with Motor, Switch;
  package Table_XY is

    type Motor_Access_Type is access all Motor.Object_Type'Class;
    type Switch_Access_Type is access all Switch.Object_Type'Class;

    type Object_Type is record
       X_Motor : Motor_Access_Type;
       Y_Motor : Motor_Access_Type;
       X_Limit : Switch_Access_Type;
       Y_Limit : Switch_Access_Type;
    end record;

    procedure Set_Velocity_X ( Object : in out Object_Type;
                               Velocity : in Motor.Velocity_Type );
    -- and so forth

  end Table_XY;

My main issues:

  (1) What do I do about the constructor? As I understand C++,
      I need to force the user to supply values for the components of
      Object_Type when something of that type is declared. How do I do
this?

  (2) If I'm reading it correctly, the C++ interface exposes the details
of
      the table, although it provides procedures to manipulate it.
However,
      I'm thinking of making Object_Type limited private anyway, since
      otherwise it seems silly to have the procedures/functions that are
      declared here. (More of a style issue than anything...)

Any comments?

--
LMTAS - The Fighter Enterprise - "Our Brand Means Quality"
For job listings, other info: http://www.lmtas.com or
http://www.lmco.com




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

* Re: Converting C++ class to Ada
  1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
@ 1996-12-11  0:00 ` Norman H. Cohen
  1996-12-12  0:00   ` Jon S Anthony
  1996-12-11  0:00 ` Jon S Anthony
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 22+ messages in thread
From: Norman H. Cohen @ 1996-12-11  0:00 UTC (permalink / raw)



Ken Garlington wrote:

>   (1) What do I do about the constructor? As I understand C++,
>       I need to force the user to supply values for the components of
>       Object_Type when something of that type is declared. How do I do
> this?

Stephen Leake mentioned one approach: discriminants.  Stephen is worried
about the fact that the discriminant values cannot change, but if you
are not too worried about space, you can have both a discriminant and an
ordinary record component for each piece of data that must be specified
upon creation of the object.  You can make your Object_Type controlled
and have its Initialize procedure copy the discriminant values into the
ordinary record components.  The only purpose of the discriminants is to
act, in effect, to parameterize the creation of an object.  (The use of
discriminants as C++-style "constructor parameters" is discussed on page
579 of Ada as a Second Language, where it is also stated that the role
of a constructor in C++ is most often played in Ada by a function
returning a new object.  Which brings us to a second approach...)

Another approach is to manipulate your objects outside the defining
package entirely in terms of references.  You provide a function that
takes the parameters needed for creating a new object and returns a
reference to the newly created object.  To ensure that Object_Type
objects cannot be created in any other way, make Object_Type both
limited and indefinite:

   type Object_Type (<>) is limited private;
   type Reference_Type is access Object_Type;
   function New_Object (...) return Reference_Type;

Outside of its defining package, Object_Type is indefinite, so an object
of the type can only be created if an initial value is specified for it
(in an object declaration or allocator), but Object_Type is also
limited, so no initial value can be specified for an object of this
type!  In other words, an Object_Type object cannot be declared or
allocated outside its defining package.  The corresponding full type
need not be either limited or indefinite, so inside the package body you
are free to allocate objects of the type and return the resulting access
values to the caller.  (Another example of this approach can be found on
pages 489-490 of Ada as a Second Language.)

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Converting C++ class to Ada
  1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
  1996-12-11  0:00 ` Norman H. Cohen
  1996-12-11  0:00 ` Jon S Anthony
@ 1996-12-11  0:00 ` Larry Kilgallen
  1996-12-11  0:00 ` Stephen Leake
  1996-12-12  0:00 ` Dale Stanbrough
  4 siblings, 0 replies; 22+ messages in thread
From: Larry Kilgallen @ 1996-12-11  0:00 UTC (permalink / raw)



In article <32ADF183.7195@lmtas.lmco.com>, Ken Garlington <GarlingtonKE@lmtas.lmco.com> writes:
> In an attempt to better understand both C++ and Ada, I've been
> converting some C++ code into Ada. I'm struggling with this particular
> class:

> Any comments?

I have a great interest in this subject but not even enough knowledge
to ask the right questions, so I look forward with interest to comments
from those with expertise.

Larry Kilgallen




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

* Re: Converting C++ class to Ada
  1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
                   ` (2 preceding siblings ...)
  1996-12-11  0:00 ` Larry Kilgallen
@ 1996-12-11  0:00 ` Stephen Leake
  1996-12-13  0:00   ` Stephen Leake
  1996-12-12  0:00 ` Dale Stanbrough
  4 siblings, 1 reply; 22+ messages in thread
From: Stephen Leake @ 1996-12-11  0:00 UTC (permalink / raw)



Ken Garlington wrote:
> 
> In an attempt to better understand both C++ and Ada, I've been
> converting some C++ code into Ada. I'm struggling with this particular
> class:
> 
>   class CTableXY
>   {
>   public:
>     CMotor&   XMotor;
>     CMotor&   YMotor;
>     CSwitch&  XLimit;
>     CSwitch&  YLimit;
>     CTableXY( CMotor& xmotor, CMotor& ymotor,
>        CSwitch& xlim, CSwitch& ylim ) :
>        XMotor(xmotor), YMotor(ymotor),
>        XLimit(xlim), YLimit(ylim) {}
>     void SetVelocityX( float vel )
>     { XMotor.SetSpeed( vel ); }
>     void SetVelocityY( float vel )
>     { YMotor.SetSpeed( vel ); }
>     int GetSwitchX( void ) { return
>       XLimit.isOpen(); }
>     int GetSwitchY( void ) { return
>       YLimit.isOpen(); }
>   };
> 
> It seems to me that the straightforward Ada translation is something
> like:
> 
>   with Motor, Switch;
>   package Table_XY is
> 
>     type Motor_Access_Type is access all Motor.Object_Type'Class;
>     type Switch_Access_Type is access all Switch.Object_Type'Class;
> 
>     type Object_Type is record
>        X_Motor : Motor_Access_Type;
>        Y_Motor : Motor_Access_Type;
>        X_Limit : Switch_Access_Type;
>        Y_Limit : Switch_Access_Type;
>     end record;
> 
>     procedure Set_Velocity_X ( Object : in out Object_Type;
>                                Velocity : in Motor.Velocity_Type );
>     -- and so forth
> 
>   end Table_XY;

I'm not clear why a class would have reference members, but if I were
building this type, the components of Object_Type would NOT be access
types; I want the class to have control over when they change. I'll
ignore this issue in the following.

> 
> My main issues:
> 
>   (1) What do I do about the constructor? As I understand C++,
>       I need to force the user to supply values for the components of
>       Object_Type when something of that type is declared. How do I do
> this?

I believe the only way to force the user to provide values when
declaring an object is to use discriminants. However, this is not what
you want to do, because you cannot easily change the discriminants
later.

If you make Object_Type private, you can include an Initialized
component that defaults to False, and then provide an Initialize
procedure that sets all the other components. Then all the subprograms
that operate on Object_Type can check Initialize and raise an exception.
Not the same as C++, but similar.

Ahah! the Initialized component could be a discriminant without
defaults; then the user must provide a full aggregate when the object is
declared:

type Object_Type (Initialized : BOOLEAN) is record
   case Initialized is
   when False =>
      null;
   when True =>
     X_Motor : Motor_Access_Type;
     Y_Motor : Motor_Access_Type;
     X_Limit : Switch_Access_Type;
     Y_Limit : Switch_Access_Type;
   end case;
end record;

> 
>   (2) If I'm reading it correctly, the C++ interface exposes the details
> of
>       the table, although it provides procedures to manipulate it.
> However,
>       I'm thinking of making Object_Type limited private anyway, since
>       otherwise it seems silly to have the procedures/functions that are
>       declared here. (More of a style issue than anything...)
> 
> Any comments?

Definitely make it private, and probably limited. If you are controlling
a motor, you cannot let the user change the velocity without checking
the limits! Similarly, only one copy of the "current velocity" may exist
for each motor; assignment is a bad idea.

> 
> --
> LMTAS - The Fighter Enterprise - "Our Brand Means Quality"
> For job listings, other info: http://www.lmtas.com or
> http://www.lmco.com

-- 
- Stephe




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

* Re: Converting C++ class to Ada
  1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
  1996-12-11  0:00 ` Norman H. Cohen
@ 1996-12-11  0:00 ` Jon S Anthony
  1996-12-12  0:00   ` Ken Garlington
                     ` (4 more replies)
  1996-12-11  0:00 ` Larry Kilgallen
                   ` (2 subsequent siblings)
  4 siblings, 5 replies; 22+ messages in thread
From: Jon S Anthony @ 1996-12-11  0:00 UTC (permalink / raw)



In article <32ADF183.7195@lmtas.lmco.com> Ken Garlington <GarlingtonKE@lmtas.lmco.com> writes:

>   class CTableXY
>   {
>   public:
>     CMotor&   XMotor;
>     CMotor&   YMotor;
>     CSwitch&  XLimit;
>     CSwitch&  YLimit;
>     CTableXY( CMotor& xmotor, CMotor& ymotor,
>        CSwitch& xlim, CSwitch& ylim ) :
>        XMotor(xmotor), YMotor(ymotor),
>        XLimit(xlim), YLimit(ylim) {}
>     void SetVelocityX( float vel )
>     { XMotor.SetSpeed( vel ); }
>     void SetVelocityY( float vel )
>     { YMotor.SetSpeed( vel ); }
>     int GetSwitchX( void ) { return
>       XLimit.isOpen(); }
>     int GetSwitchY( void ) { return
>       YLimit.isOpen(); }
>   };
> 
> It seems to me that the straightforward Ada translation is something
> like:
> 
>   with Motor, Switch;
>   package Table_XY is
> 
>     type Motor_Access_Type is access all Motor.Object_Type'Class;
>     type Switch_Access_Type is access all Switch.Object_Type'Class;
> 
>     type Object_Type is record
>        X_Motor : Motor_Access_Type;
>        Y_Motor : Motor_Access_Type;
>        X_Limit : Switch_Access_Type;
>        Y_Limit : Switch_Access_Type;
>     end record;
> 
>     procedure Set_Velocity_X ( Object : in out Object_Type;
>                                Velocity : in Motor.Velocity_Type );
>     -- and so forth
> 
>   end Table_XY;
> 
> My main issues:
> 
>   (1) What do I do about the constructor? As I understand C++,
>       I need to force the user to supply values for the components of
>       Object_Type when something of that type is declared. How do I do
> this?

Two ways:

  1. type Object_Type (
         X_Motor : Motor_Access_Type;
         Y_Motor : Motor_Access_Type;
         X_Limit : Switch_Access_Type;
         Y_Limit : Switch_Access_Type ) is null record; (or better: is private)

  Now, whenever an object of this type is declared, you will have to supply
  the discriminants and there you are.  Note that this works for the case of
  _limited_ types too.

  2. type Object_Type (<>) is private;
     function Make (
         X_Motor : Motor_Access_Type;
         Y_Motor : Motor_Access_Type;
         X_Limit : Switch_Access_Type;
         Y_Limit : Switch_Access_Type ) return Object_Type;
...
 private
     type Object_Type is record ... as you have it
        OR
     type Object_Type (... as in 1.

  Now, whenever an object of this type is declared you will have to
  initialize it.  The only way you give is via Make, so you can force
  the supply of arguments.  This way is especially useful with instances
  of limited types via allocators as you can have your own pool and know
  all clients must use that pool.


>   (2) If I'm reading it correctly, the C++ interface exposes the details
> of the table, although it provides procedures to manipulate it.
> However,
>       I'm thinking of making Object_Type limited private anyway, since
>       otherwise it seems silly to have the procedures/functions that are
>       declared here. (More of a style issue than anything...)

Right.  Except I don't see this as simply a "style" issue.  It is more
important than that.  The C++ hack..ah..coder goofed and should have made
the motor and switch stuff private (or protected).

/Jon

-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Norman H. Cohen
@ 1996-12-12  0:00   ` Jon S Anthony
  0 siblings, 0 replies; 22+ messages in thread
From: Jon S Anthony @ 1996-12-12  0:00 UTC (permalink / raw)



In article <32AF3A52.1340@watson.ibm.com> "Norman H. Cohen" <ncohen@watson.ibm.com> writes:

>    type Object_Type (<>) is limited private;
>    type Reference_Type is access Object_Type;
>    function New_Object (...) return Reference_Type;
> 
> Outside of its defining package, Object_Type is indefinite, so an object
> of the type can only be created if an initial value is specified for it
> (in an object declaration or allocator), but Object_Type is also
> limited, so no initial value can be specified for an object of this
> type!  In other words, an Object_Type object cannot be declared or
> allocated outside its defining package.  The corresponding full type
> need not be either limited or indefinite, so inside the package body you
  ^^^^^^^^^^^^^^^^^^^^^^^^^^
> are free to allocate objects of the type and return the resulting access
> values to the caller.  (Another example of this approach can be found on
> pages 489-490 of Ada as a Second Language.)

Note that this is _not_ true if the type is tagged...

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





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

* Constructors for Ada (was: Converting C++ class to Ada)
  1996-12-12  0:00 ` Dale Stanbrough
@ 1996-12-12  0:00   ` Matthew Heaney
  1996-12-13  0:00     ` Norman H. Cohen
  1996-12-17  0:00   ` Robert I. Eachus
  1 sibling, 1 reply; 22+ messages in thread
From: Matthew Heaney @ 1996-12-12  0:00 UTC (permalink / raw)



In article <58npck$iku$1@goanna.cs.rmit.edu.au>, Dale Stanbrough
<dale@goanna.cs.rmit.edu.au> wrote:

   (1) What do I do about the constructor? As I understand C++,
>       I need to force the user to supply values for the components of
>       Object_Type when something of that type is declared. How do I do
> this?"
>
>The only way to force this seems to be the use of private types with
>discriminants.
>
>        type Object_Type(<>) is private;
>        
>which says this _may_ have discriminants, but that's private.
>
>The only way to initialize and object, and you are forced to, is 
>via a function.
>
>        Item : Object_Type; -- illegal, must be initialized
>        
>        Item : Object_Type := Init(....); -- Ok.
>        
>The full type definition does not have to have the discriminants.
>IMHO, it would have been nicer to be able to say "this object must
>be initialized when declared" by using a different mechanism to this 
>(rather obscure) one.

Your solution is correct: call a function that returns a object of the
type.  Different functions can perform different kinds of initialization. 
But this only works if the type is non-limited (which is the normal case
anyway).

I'm not sure this technique - making the type indefinate to force
initialization - qualifies as "obscure," though.  Rather, it's just that we
haven't all been programming in Ada 95 long enough for this to be an
obvious idiom.

However, you have touched on an area where I feel there is an omission in
the language.

The issue I have with the language is that there is an asymmetry between
how stack objects are initialized and how heap objects are initialized.

For example, to initialize an object on the heap:

type Integer_Access is access Integer;
O : Integer_Access := new Integer'(4);

Why shouldn't I be able to do that for stack objects too?

O : Integer'(4);

What I'd like (and Dale too, it seems) is a way to initialize objects (on
the stack or heap) by invoking a subprogram explicitly identified as a
constructor, and be able to do so irrespective of whether the type is
limited or non-limited.

The problem is that in Ada initialization of an object on the stack
requires assignment, but this not need be so.  It's just a syntactic quirk
that prevents me from calling an initialization subprogram during
elaboration of a limited object.

For example, suppose I had a persistant queue.  I'd like to read its state
from disk by doing this:

Q : Queue'(Name => "my_queue.dat");

Though I suppose I could do that now if my queue were non-limited by using
a function:

Q : Queue := Create (Name => "my_queue.dat");


But suppose my type were limited.  For  example, I'd like to open a file
during elaboration of the file object:

F : File_Type'(Name => "my_file.dat", Mode => In_File);

That's something I can't do now, because type File_Type is limited private. 
So I have to do this

   F : File_Type;
begin
   Open (F, Name => "my_file.dat", Mode => In_File);


I'd like to see a subprogram explicitly identified as a constructor:

   type T is limited private;

   constructor T (Name : in String; Mode : in File_Mode);

or maybe 

   constructor (Name : in String; Mode : in File_Mode) initializes T;

But we can do better.  Ian Joyner made the point in his C++ critique that
it's often not obvious what each constructor does, because you only get the
argument part of the signiture - there is no meaningful name.  He points
out that in Eiffel each constructor has a name, too, unlike C++.

So maybe my hypothetical syntax is better if I can do this:

   constructor T Open (Name : in String; Mode : in File_Mode);

or maybe

   constructor Open (Name : in String; Mode : in File_Mode) initializes T;

Then we could use the name during initialization:

F : File_Type'Open (Name => "my_file.dat", Mode => In_File);

This feature is my current favorite for inclusion in a future version of
the language.

What do you think?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Converting C++ class to Ada
  1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
                   ` (3 preceding siblings ...)
  1996-12-11  0:00 ` Stephen Leake
@ 1996-12-12  0:00 ` Dale Stanbrough
  1996-12-12  0:00   ` Constructors for Ada (was: Converting C++ class to Ada) Matthew Heaney
  1996-12-17  0:00   ` Robert I. Eachus
  4 siblings, 2 replies; 22+ messages in thread
From: Dale Stanbrough @ 1996-12-12  0:00 UTC (permalink / raw)



"My main issues:
 
   (1) What do I do about the constructor? As I understand C++,
       I need to force the user to supply values for the components of
       Object_Type when something of that type is declared. How do I do
 this?"



The only way to force this seems to be the use of private types with
discriminants.


	type Object_Type(<>) is private;
	
which says this _may_ have discriminants, but that's private.

The only way to initialize and object, and you are forced to, is 
via a function.

E.g.

	Item : Object_Type; -- illegal, must be initialized
	
	Item : Object_Type := Init(....); -- Ok.
	
	
The full type definition does not have to have the discriminants.
IMHO, it would have been nicer to be able to say "this object must
be initialized when declared" by using a different mechanism to this 
(rather obscure) one.


Dale




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Jon S Anthony
@ 1996-12-12  0:00   ` Ken Garlington
  1996-12-18  0:00   ` Jon S Anthony
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 22+ messages in thread
From: Ken Garlington @ 1996-12-12  0:00 UTC (permalink / raw)



Jon S Anthony wrote:
> 
> Two ways:
> 
>   1. type Object_Type (
>          X_Motor : Motor_Access_Type;
>          Y_Motor : Motor_Access_Type;
>          X_Limit : Switch_Access_Type;
>          Y_Limit : Switch_Access_Type ) is null record; (or better: is private)
> 
>   Now, whenever an object of this type is declared, you will have to supply
>   the discriminants and there you are.  Note that this works for the case of
>   _limited_ types too.

However, will I be able to update the discriminants? Norman Cohen points
out that I could have an updatable copy within the record, but
that seems a little clumsy. Also, if I wanted to make sure that "null"
wasn't used as one of the discriminants, would I have to use "access
Motor.Object_Type" rather than the declared access type?

>   2. type Object_Type (<>) is private;
>      function Make (
>          X_Motor : Motor_Access_Type;
>          Y_Motor : Motor_Access_Type;
>          X_Limit : Switch_Access_Type;
>          Y_Limit : Switch_Access_Type ) return Object_Type;
> ...
>  private
>      type Object_Type is record ... as you have it
>         OR
>      type Object_Type (... as in 1.
> 
>   Now, whenever an object of this type is declared you will have to
>   initialize it.  The only way you give is via Make, so you can force
>   the supply of arguments.  This way is especially useful with instances
>   of limited types via allocators as you can have your own pool and know
>   all clients must use that pool.

OK. This looks like it might be a winner. I'll try it and see.

> Right.  Except I don't see this as simply a "style" issue.  It is more
> important than that.  The C++ hack..ah..coder goofed and should have made
> the motor and switch stuff private (or protected).

OK. I'm trying not to stray too far from the C++ code, since I would
like
for C++ folks to be able to compare it with the Ada version, but I think
in this case I'll make an exception and make it private.

--
LMTAS - The Fighter Enterprise - "Our Brand Means Quality"
For job listings, other info: http://www.lmtas.com or
http://www.lmco.com




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

* Re: Constructors for Ada (was: Converting C++ class to Ada)
  1996-12-13  0:00     ` Norman H. Cohen
@ 1996-12-13  0:00       ` Matthew Heaney
  0 siblings, 0 replies; 22+ messages in thread
From: Matthew Heaney @ 1996-12-13  0:00 UTC (permalink / raw)



In article <32B17EFC.4BC7@watson.ibm.com>, ncohen@watson.ibm.com wrote:

>> The issue I have with the language is that there is an asymmetry between
>> how stack objects are initialized and how heap objects are initialized.
>> 
>> For example, to initialize an object on the heap:
>> 
>> type Integer_Access is access Integer;
>> O : Integer_Access := new Integer'(4);
>> 
>> Why shouldn't I be able to do that for stack objects too?
>> 
>> O : Integer'(4);

[snip]

>
>I don't understand Matthew's point.  Why is the syntax 
>
>   O : Integer'(4);
>
>in any way preferable to 
>
>   O : Integer := 4;
>
>?  After all, if LT is a limited type, it cannot be initialized in
>either an object declaration or an allocator.  That is,
>
>  new LT'(X);
>
>is every bit as illegal as
>
>  O : LT := X;
>
>and for very good reason:  It entails making a copy of X.

I was using that style of initialization as an analogy only.  Sorry about that!

The way the language is now, it's sort of like there's a predefined
constructor that takes the type as an  argument.  For example,

type T is private;

constructor T (Initial_Value : in T);   -- a "built-in" constructor

And for objects on the heap only, I can "invoke" this constructor:

X : T;
O := new T'(X);

What I'm asking for is a way to define other constructors, that take other
than type T as an argument.  For example,

constructor T (File_Name : in String);

Having that would allow me to do this

O : T'(File_Name => "my_file.dat");

Yes, I can already do something very close to that for non-limited types -
by using a function that returns a value of the type.  But my motivation
was being able to that for limited types too.

I can't use a function to return a value of the limited type during
elaboration of a limited object, so I had to invent some other way to do
that.  Thus the new syntax.

I can't do this

function Initial_Value (<custom params here>) return T;
O : LT := Initial_Value (...);

because I don't have assignment for limited types.  So let's solve the
problem by doing this

O : LT'Initial_Value (...);


>Matthew suggests that it would be useful to specify parameters in the
>declaration of a limited object to control how the object is
>initialized.

Yes.

>Since it is already possible to force a limited object to
>have a default initial state, and to change the object's state by
>calling a procedure declared in the same package as the limited type, I
see no compelling need for this.

Then we have a philosophical difference.  I would like to allow the user to
have more control of the initial state of a limited object, by invoking the
constructor of his choice.  And to be able to do it in the declarative
region.

Maybe the need for such a mechanism isn't "compelling," but to me it's in
the "really desirable" category.
 
>(Furthermore, as stated in a previous
>message, the same effect can often be achieved by deriving the limited
>type from Limited_Controlled and giving the type discriminants that are
>read by the type's Initialize procedure.

Again, we have a philosophical difference.  To me using discriminants to
"initialize" an object is a misuse of the language.  I don't believe
discriminants should be used for that purpose.

It seems to me you're fighting the language.  Why fight?  If you really
want to custom initialize an object, why not build in a proper mechanism to
do so?

>> But suppose my type were limited.  For  example, I'd like to open a file
>> during elaboration of the file object:
>> 
>> F : File_Type'(Name => "my_file.dat", Mode => In_File);
>> 
>> That's something I can't do now, because type File_Type is limited private.
>> So I have to do this
>> 
>>    F : File_Type;
>> begin
>>    Open (F, Name => "my_file.dat", Mode => In_File);
>
>What's so bad about with that?

I didn't say it was bad!  It's just that I wanted a uniform way of
initializing objects, that applies irrespective of whether the type is
limited or non-limited.

The syntax rules prevent one from initializing a limited object in the
declarative region (because no assignment is available).  Why should
initialization of limited objects have to be done differently?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Constructors for Ada (was: Converting C++ class to Ada)
  1996-12-12  0:00   ` Constructors for Ada (was: Converting C++ class to Ada) Matthew Heaney
@ 1996-12-13  0:00     ` Norman H. Cohen
  1996-12-13  0:00       ` Matthew Heaney
  0 siblings, 1 reply; 22+ messages in thread
From: Norman H. Cohen @ 1996-12-13  0:00 UTC (permalink / raw)



Matthew Heaney wrote:

> The issue I have with the language is that there is an asymmetry between
> how stack objects are initialized and how heap objects are initialized.
> 
> For example, to initialize an object on the heap:
> 
> type Integer_Access is access Integer;
> O : Integer_Access := new Integer'(4);
> 
> Why shouldn't I be able to do that for stack objects too?
> 
> O : Integer'(4);
> 
> What I'd like (and Dale too, it seems) is a way to initialize objects (on
> the stack or heap) by invoking a subprogram explicitly identified as a
> constructor, and be able to do so irrespective of whether the type is
> limited or non-limited.
> 
> The problem is that in Ada initialization of an object on the stack
> requires assignment, but this not need be so.  It's just a syntactic quirk
> that prevents me from calling an initialization subprogram during
> elaboration of a limited object.

I don't understand Matthew's point.  Why is the syntax 

   O : Integer'(4);

in any way preferable to 

   O : Integer := 4;

?  After all, if LT is a limited type, it cannot be initialized in
either an object declaration or an allocator.  That is,

  new LT'(X);

is every bit as illegal as

  O : LT := X;

and for very good reason:  It entails making a copy of X.

Matthew suggests that it would be useful to specify parameters in the
declaration of a limited object to control how the object is
initialized.  Since it is already possible to force a limited object to
have a default initial state, and to change the object's state by
calling a procedure declared in the same package as the limited type, I
see no compelling need for this.  (Furthermore, as stated in a previous
message, the same effect can often be achieved by deriving the limited
type from Limited_Controlled and giving the type discriminants that are
read by the type's Initialize procedure.

> But suppose my type were limited.  For  example, I'd like to open a file
> during elaboration of the file object:
> 
> F : File_Type'(Name => "my_file.dat", Mode => In_File);
> 
> That's something I can't do now, because type File_Type is limited private.
> So I have to do this
> 
>    F : File_Type;
> begin
>    Open (F, Name => "my_file.dat", Mode => In_File);

What's so bad about with that?

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Stephen Leake
@ 1996-12-13  0:00   ` Stephen Leake
  0 siblings, 0 replies; 22+ messages in thread
From: Stephen Leake @ 1996-12-13  0:00 UTC (permalink / raw)



Since yesterday, I've talked to a C++ guru, and have some further
information :)

Stephen Leake wrote:
> 
> Ken Garlington wrote:
> >
> > In an attempt to better understand both C++ and Ada, I've been
> > converting some C++ code into Ada. I'm struggling with this particular
> > class:
> >
> >   class CTableXY
> >   {
> >   public:
> >     CMotor&   XMotor;
> >     CMotor&   YMotor;
> >     CSwitch&  XLimit;
> >     CSwitch&  YLimit;
> >     CTableXY( CMotor& xmotor, CMotor& ymotor,
> >        CSwitch& xlim, CSwitch& ylim ) :
> >        XMotor(xmotor), YMotor(ymotor),
> >        XLimit(xlim), YLimit(ylim) {}
> >     void SetVelocityX( float vel )
> >     { XMotor.SetSpeed( vel ); }
> >     void SetVelocityY( float vel )
> >     { YMotor.SetSpeed( vel ); }
> >     int GetSwitchX( void ) { return
> >       XLimit.isOpen(); }
> >     int GetSwitchY( void ) { return
> >       YLimit.isOpen(); }
> >   };
> >
> > It seems to me that the straightforward Ada translation is something
> > like:
> >
> >   with Motor, Switch;
> >   package Table_XY is
> >
> >     type Motor_Access_Type is access all Motor.Object_Type'Class;
> >     type Switch_Access_Type is access all Switch.Object_Type'Class;
> >
> >     type Object_Type is record
> >        X_Motor : Motor_Access_Type;
> >        Y_Motor : Motor_Access_Type;
> >        X_Limit : Switch_Access_Type;
> >        Y_Limit : Switch_Access_Type;
> >     end record;
> >
> >     procedure Set_Velocity_X ( Object : in out Object_Type;
> >                                Velocity : in Motor.Velocity_Type );
> >     -- and so forth
> >
> >   end Table_XY;
> 
> I'm not clear why a class would have reference members, but if I were
> building this type, the components of Object_Type would NOT be access
> types; I want the class to have control over when they change. I'll
> ignore this issue in the following.

A C++ reference is a constant (it always refers to the same object), so
using an access type in Ada definitely loses something (you can change
what object it points to). My C++ guru says he uses references as class
members mainly for temporary objects in windowing systems; binding a
widget and a gidget together into a whatsis, where the widget and gidget
already exist.

> 
> >
> > My main issues:
> >
> >   (1) What do I do about the constructor? As I understand C++,
> >       I need to force the user to supply values for the components of
> >       Object_Type when something of that type is declared. How do I do
> > this?
> 
> Ahah! the Initialized component could be a discriminant without
> defaults; then the user must provide a full aggregate when the object is
> declared:
> 
> type Object_Type (Initialized : BOOLEAN) is record
>    case Initialized is
>    when False =>
>       null;
>    when True =>
>      X_Motor : Motor_Access_Type;
>      Y_Motor : Motor_Access_Type;
>      X_Limit : Switch_Access_Type;
>      Y_Limit : Switch_Access_Type;
>    end case;
> end record;

Oops; this doesn't get there. It is perfectly legal to declare:

Foo : Object_Type (True);

and the fields exist without being initialized.


-- 
- Stephe




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

* Re: Constructors for Ada (was: Converting C++ class to Ada)
  1996-12-12  0:00 ` Dale Stanbrough
  1996-12-12  0:00   ` Constructors for Ada (was: Converting C++ class to Ada) Matthew Heaney
@ 1996-12-17  0:00   ` Robert I. Eachus
  1 sibling, 0 replies; 22+ messages in thread
From: Robert I. Eachus @ 1996-12-17  0:00 UTC (permalink / raw)



In article <mheaney-ya023280001312961835130001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

 > Then we have a philosophical difference.  I would like to allow the
 > user to have more control of the initial state of a limited object,
 > by invoking the constructor of his choice.  And to be able to do it
 > in the declarative region.

   Let's see.  In Ada 83 the concept of limited types was introduced
to allow treatment of task objects to be consistant with that of other
objects.  As a result you can have objects with tasks as components,
etc.  But the characteristic of limited types is that they don't have
an assignment operation.  (By default limited types don't have "="
either, but an "=" function can be added, as can a ">", etc.)

   Having said that, Ada 95 went through several gyrations about
functions returning limited types.  The final result is at
6.5(11..21) and defines "return-by-reference" types.  The net effect
of all this is that you can have a function returning a limited type,
take 'ACCESS of the call and assign it to an access value:

   type File_Access is access Text_IO.File_Type;

   function Open(Name: in String;
                 Mode: in Text_IO.File_Mode := Text_IO.In_File;
                 Form: in String := "")
          return Text_IO.File_Type;
   ...

   A_File: File_Access := Open("My_File")'Access;
   ...

   Text_IO.Close(A_File.all);

   If you think it is cleaner you can even define Open to return a
value of type File_Access, but I don't recommend it.  RM 3.10.2(10)
has another bit of magic about functions which have
return-by-reference return values.  The static nesting depth of the
return value is that of the scope containing the body of the function.
This allows you to avoid accessability checks and not be required to
manage the garbage collection.  (In most implementations, the used
file objects will be reclaimed when you exit the scope where the open
function was declared, so there are cases where you do want to nest
it.)

   (Of course you can be clever and define two functions, one of which
calls the other, and either hope that the comiler figures out that the
accessability check can be made statically, or use inlining to provide
a clue.)

 > The syntax rules prevent one from initializing a limited object in
 > the declarative region (because no assignment is available).  Why
 > should initialization of limited objects have to be done
 > differently?

   Because no assignment is availiable?  Remember that there are going
to be limited objects for which assignment is not available anywhere,
such as objects containing tasks or protected objects.  But notice
that you are not prevented from initializing limited objects in a
declarative region, you are only prevented from doing it by
assignment.  That is a prohibition that is not specific to declarative
parts.  Of course it is REAL ugly to initialize an object as the side
effect of a later declaration, but it is not prohibited.


--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Jon S Anthony
  1996-12-12  0:00   ` Ken Garlington
@ 1996-12-18  0:00   ` Jon S Anthony
  1996-12-18  0:00     ` Matthew Heaney
  1996-12-19  0:00     ` Robert A Duff
  1996-12-20  0:00   ` Norman H. Cohen
                     ` (2 subsequent siblings)
  4 siblings, 2 replies; 22+ messages in thread
From: Jon S Anthony @ 1996-12-18  0:00 UTC (permalink / raw)



In article <32B05137.733A@lmtas.lmco.com> Ken Garlington <GarlingtonKE@lmtas.lmco.com> writes:

> However, will I be able to update the discriminants? Norman Cohen points

No.

> out that I could have an updatable copy within the record, but

Yup.

> that seems a little clumsy.

I would tend to agree.

> Also, if I wanted to make sure that "null" wasn't used as one of the
> discriminants, would I have to use "access Motor.Object_Type" rather
> than the declared access type?

Neither will prevent that.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





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

* Re: Converting C++ class to Ada
  1996-12-18  0:00   ` Jon S Anthony
@ 1996-12-18  0:00     ` Matthew Heaney
  1996-12-19  0:00     ` Robert A Duff
  1 sibling, 0 replies; 22+ messages in thread
From: Matthew Heaney @ 1996-12-18  0:00 UTC (permalink / raw)



In article <JSA.96Dec18184555@alexandria>, jsa@alexandria (Jon S Anthony) wrote:


>> Also, if I wanted to make sure that "null" wasn't used as one of the
>> discriminants, would I have to use "access Motor.Object_Type" rather
>> than the declared access type?
>
>Neither will prevent that.

I thought that access discriminants (and parameters) without an explicit
type raise Program_Error when you pass "null" as the value?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
mheaney@ni.net
(818) 985-1271




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

* Re: Converting C++ class to Ada
  1996-12-18  0:00   ` Jon S Anthony
  1996-12-18  0:00     ` Matthew Heaney
@ 1996-12-19  0:00     ` Robert A Duff
  1996-12-20  0:00       ` Stephen Leake
  1 sibling, 1 reply; 22+ messages in thread
From: Robert A Duff @ 1996-12-19  0:00 UTC (permalink / raw)



In article <JSA.96Dec18184555@alexandria>,
Jon S Anthony <jsa@alexandria> wrote:
>> Also, if I wanted to make sure that "null" wasn't used as one of the
>> discriminants, would I have to use "access Motor.Object_Type" rather
>> than the declared access type?
>
>Neither will prevent that.

A value of an anonymous access type can never be null.  (This includes
both access parameters and access discriminants.)  Run-time checks
ensure this.

- Bob




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Jon S Anthony
                     ` (2 preceding siblings ...)
  1996-12-20  0:00   ` Norman H. Cohen
@ 1996-12-20  0:00   ` Jon S Anthony
  1996-12-20  0:00     ` Mitch Gart
  1996-12-21  0:00   ` Jon S Anthony
  4 siblings, 1 reply; 22+ messages in thread
From: Jon S Anthony @ 1996-12-20  0:00 UTC (permalink / raw)



In article <mheaney-ya023280001812962110410001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

> In article <JSA.96Dec18184555@alexandria>, jsa@alexandria (Jon S Anthony) wrote:
> 
> 
> >> Also, if I wanted to make sure that "null" wasn't used as one of the
> >> discriminants, would I have to use "access Motor.Object_Type" rather
> >> than the declared access type?
> >
> >Neither will prevent that.
> 
> I thought that access discriminants (and parameters) without an explicit
> type raise Program_Error when you pass "null" as the value?

CE is raised if a null value is passed to an access _parameter_.  I
have never seen anything indicating that CE (or PE) is raised if a
null value is given for the value of an access _discriminant_.  A good
thing IMO on both counts.  See in particular 11.5(11)

Of course, given a recent little discussion on the GNAT chat list I
could simply have not found it yet... :-) But really, this point seems
pretty clear!

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





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

* Re: Converting C++ class to Ada
  1996-12-20  0:00   ` Jon S Anthony
@ 1996-12-20  0:00     ` Mitch Gart
  0 siblings, 0 replies; 22+ messages in thread
From: Mitch Gart @ 1996-12-20  0:00 UTC (permalink / raw)



Jon S Anthony (jsa@alexandria) wrote:

: CE is raised if a null value is passed to an access _parameter_.  
(snip)
: A good thing IMO on both counts.  See in particular 11.5(11)

I think this is a mistake in Ada 95.  Not allowing null for an
access parameter makes it harder to interface to C:

    procedure P(param: access thing);
    pragma import(C, P);

You can't call P(null) even though the C function may have 
semantics defined for null.  You have to make up a named
access type for the parameter.

Users of Win32Ada and X11Ada will notice that the bindings
contain access parameters in many places.  This is a mistake
that needs fixing given the above Ada 95 rule.

- Mitch Gart
- mg@inmet.com




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

* Re: Converting C++ class to Ada
  1996-12-19  0:00     ` Robert A Duff
@ 1996-12-20  0:00       ` Stephen Leake
  1996-12-20  0:00         ` Robert A Duff
  0 siblings, 1 reply; 22+ messages in thread
From: Stephen Leake @ 1996-12-20  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <JSA.96Dec18184555@alexandria>,
> Jon S Anthony <jsa@alexandria> wrote:
> >> Also, if I wanted to make sure that "null" wasn't used as one of the
> >> discriminants, would I have to use "access Motor.Object_Type" rather
> >> than the declared access type?
> >
> >Neither will prevent that.
> 
> A value of an anonymous access type can never be null.  (This includes
> both access parameters and access discriminants.)  Run-time checks
> ensure this.
> 
> - Bob

I can't find a rule in the RM that says this. In "Ada as a Second
Language", page 491, Norman Cohen says "Elaboration of a discriminant
constraint raises the exception Constriant_Error if the value given for
an access disciminant is null". So I believe an access discriminant
cannot be null, but I'm trying to hone my RM reading skills. Searching
for "access discriminant" gave no rule regarding null values. As Jon
Anthony pointed out, 11.5, which lists ALL defined checks, does not
mention checking access discriminants for null, only access parameters.
So where is the rule?
-- 
- Stephe




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Jon S Anthony
  1996-12-12  0:00   ` Ken Garlington
  1996-12-18  0:00   ` Jon S Anthony
@ 1996-12-20  0:00   ` Norman H. Cohen
  1996-12-20  0:00   ` Jon S Anthony
  1996-12-21  0:00   ` Jon S Anthony
  4 siblings, 0 replies; 22+ messages in thread
From: Norman H. Cohen @ 1996-12-20  0:00 UTC (permalink / raw)



(Removing comp.lang.c++ from list of newsgroups.)

Jon S Anthony wrote:
 
> In article <mheaney-ya023280001812962110410001@news.ni.net> mheaney@ni.net (Matthew 
> Heaney) writes:
> 
...
> > I thought that access discriminants (and parameters) without an explicit
> > type raise Program_Error when you pass "null" as the value?
> 
> CE is raised if a null value is passed to an access _parameter_.  I
> have never seen anything indicating that CE (or PE) is raised if a
> null value is given for the value of an access _discriminant_.  A good
> thing IMO on both counts.  See in particular 11.5(11)
> 
> Of course, given a recent little discussion on the GNAT chat list I
> could simply have not found it yet... :-) But really, this point seems
> pretty clear!

No, Constraint_Error is raised for both a null access parameter and a
null access discriminant.  This point was just raised on the GNAT chat
list (probably as a result of the discussion here in comp.lang.ada), and
I replied, in part, as follows:

A null access discriminant is a run-time error.

11.5 is just a list of the language-defined checks, together with an
informal description of when the checks occur.  The definitive rules
about when a check is performed will be found in the "Dynamic Semantics"
sections describing the execution, evaluation, or elaboration of the
relevant constructs.

The relevant construct in this case is a discriminant constraint:  It is
during the elaboration of a discriminant constraint that a null access
discriminant would be caught.  RM 3.7.1(12) says:  "For the elaboration
of a discriminant_constraint, the expressions in the
discriminant_associations are evaluated in an arbitrary order and
converted to the type of the associated discriminant (which might raise
Constraint_Error--see 4.6)...."   Hidden in 4.6(49) is the rule, "If the
target type is an anonymous access type, a check is made that the value
of the operand is not null...."  (4.6(57) states that the exception
raised when this check fails is Constraint_Error.  The rule in RM
4.6(49) can be found using the index entry for "Access check".)

-- 
Norman H. Cohen
mailto:ncohen@watson.ibm.com
http://www.research.ibm.com/people/n/ncohen




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

* Re: Converting C++ class to Ada
  1996-12-20  0:00       ` Stephen Leake
@ 1996-12-20  0:00         ` Robert A Duff
  0 siblings, 0 replies; 22+ messages in thread
From: Robert A Duff @ 1996-12-20  0:00 UTC (permalink / raw)



In article <32BAB8C8.7046@gsfc.nasa.gov>,
Stephen Leake  <Stephen.Leake@gsfc.nasa.gov> wrote:
>I can't find a rule in the RM that says this.

Yeah, it's not easy to find.  :-(

Basically, lots of the rules about checks on parameter passing,
assignment, etc., are defined in terms of type conversion.  E.g. an
actual parameter is always implicitly converted to the type of the
formal (6.4.1(11)).  Then 4.6 specifies all the run-time checks for
conversions, including this null check.

Also, the *literal* null is illegal for these types.

It would have been helpful if we had said "An access param/discrim can
never be null." somewhere as a NOTE, instead of letting you figure it
out.  A statement like that is a lot more useful (though less specific)
than telling which combination of compile-time and run-time rules ensure
that it's true.  That is, to the programmer, the rule is "don't try to
make one of these things null", and it's not really important to know
the exact points of checking.  The compiler writer of course has to know
the details.

- Bob




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

* Re: Converting C++ class to Ada
  1996-12-11  0:00 ` Jon S Anthony
                     ` (3 preceding siblings ...)
  1996-12-20  0:00   ` Jon S Anthony
@ 1996-12-21  0:00   ` Jon S Anthony
  4 siblings, 0 replies; 22+ messages in thread
From: Jon S Anthony @ 1996-12-21  0:00 UTC (permalink / raw)



In article <32BAD007.648F@watson.ibm.com> "Norman H. Cohen" <ncohen@watson.ibm.com> writes:

> Jon S Anthony wrote:
>  
> > In article <mheaney-ya023280001812962110410001@news.ni.net> mheaney@ni.net (Matthew 
> > Heaney) writes:
> > 
> ...
> > > I thought that access discriminants (and parameters) without an explicit
> > > type raise Program_Error when you pass "null" as the value?
> > 
> > CE is raised if a null value is passed to an access _parameter_.  I
> > have never seen anything indicating that CE (or PE) is raised if a
> > null value is given for the value of an access _discriminant_.  A good
> > thing IMO on both counts.  See in particular 11.5(11)
> > 
> > Of course, given a recent little discussion on the GNAT chat list I
> > could simply have not found it yet... :-) But really, this point seems
> > pretty clear!

Criminey.  This one is yet another example of unnecessary RM opacity
after all... :-(


> A null access discriminant is a run-time error.
> 
> 11.5 is just a list of the language-defined checks, together with an
> informal description of when the checks occur.  The definitive rules
> about when a check is performed will be found in the "Dynamic Semantics"
> sections describing the execution, evaluation, or elaboration of the
> relevant constructs.

Yes, I actually looked around in the relevant places under this very
heading.


> Constraint_Error--see 4.6)...."   Hidden in 4.6(49) is the rule, "If the
> target type is an anonymous access type, a check is made that the value
> of the operand is not null...."  (4.6(57) states that the exception
> raised when this check fails is Constraint_Error.  The rule in RM
> 4.6(49) can be found using the index entry for "Access check".)

Even found this, but being listed under "Type Conversions" I
mistakenly did not think that it applied to the discriminant case
since that case was not also called out in 11.5(11) along with the
parameter case.

But actually, on a moments reflection this is the general rule and
must cover the parameter case as well (passing null like anything else
requires a conversion to the anonymous access type of the formal and
there you are).  This being the case it is highly unfortunate that the
discriminant case was not also called out in 11.5(11) or that the
parameter case was not _removed_ from 11.5(11).  As it sits the thing
is close to being inconsistent (at worst) or highly misleading (at
best).

Ugh!

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





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

end of thread, other threads:[~1996-12-21  0:00 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1996-12-10  0:00 Converting C++ class to Ada Ken Garlington
1996-12-11  0:00 ` Norman H. Cohen
1996-12-12  0:00   ` Jon S Anthony
1996-12-11  0:00 ` Jon S Anthony
1996-12-12  0:00   ` Ken Garlington
1996-12-18  0:00   ` Jon S Anthony
1996-12-18  0:00     ` Matthew Heaney
1996-12-19  0:00     ` Robert A Duff
1996-12-20  0:00       ` Stephen Leake
1996-12-20  0:00         ` Robert A Duff
1996-12-20  0:00   ` Norman H. Cohen
1996-12-20  0:00   ` Jon S Anthony
1996-12-20  0:00     ` Mitch Gart
1996-12-21  0:00   ` Jon S Anthony
1996-12-11  0:00 ` Larry Kilgallen
1996-12-11  0:00 ` Stephen Leake
1996-12-13  0:00   ` Stephen Leake
1996-12-12  0:00 ` Dale Stanbrough
1996-12-12  0:00   ` Constructors for Ada (was: Converting C++ class to Ada) Matthew Heaney
1996-12-13  0:00     ` Norman H. Cohen
1996-12-13  0:00       ` Matthew Heaney
1996-12-17  0:00   ` Robert I. Eachus

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