comp.lang.ada
 help / color / mirror / Atom feed
* virtual destructors
@ 2003-04-22 14:18 kat-Zygfryd
  2003-04-22 14:27 ` Stephen Leake
  2003-04-22 17:28 ` Matthew Heaney
  0 siblings, 2 replies; 17+ messages in thread
From: kat-Zygfryd @ 2003-04-22 14:18 UTC (permalink / raw)


How can I define a virtual destructor in Ada95?

Zygfryd





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

* Re: virtual destructors
  2003-04-22 14:18 virtual destructors kat-Zygfryd
@ 2003-04-22 14:27 ` Stephen Leake
  2003-04-22 14:56   ` kat-Zygfryd
  2003-04-22 17:28 ` Matthew Heaney
  1 sibling, 1 reply; 17+ messages in thread
From: Stephen Leake @ 2003-04-22 14:27 UTC (permalink / raw)


"kat-Zygfryd" <6667@wp.pl> writes:

> How can I define a virtual destructor in Ada95?

The nearest equivalent of C++ destructors is achieved by deriving from
a type declared in Ada.Finalization. Note that it is not a very close
equivalent, so to be really helpful, we need to know in a larger sense
what you are trying to do.

-- 
-- Stephe



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

* Re: virtual destructors
  2003-04-22 14:27 ` Stephen Leake
@ 2003-04-22 14:56   ` kat-Zygfryd
  2003-04-22 15:45     ` kat-Zygfryd
  2003-04-22 17:33     ` virtual destructors Matthew Heaney
  0 siblings, 2 replies; 17+ messages in thread
From: kat-Zygfryd @ 2003-04-22 14:56 UTC (permalink / raw)


"Stephen Leake" <Stephe.Leake@nasa.gov> wrote in message
news:u1xzuehed.fsf@nasa.gov...
> The nearest equivalent of C++ destructors is achieved by deriving from
> a type declared in Ada.Finalization. Note that it is not a very close
> equivalent, so to be really helpful, we need to know in a larger sense
> what you are trying to do.
>
> --
> -- Stephe

I want to have destructors working on access' to class wide types,
so that when passed a variable, an actual type destructor was
called, not a one overloaded for the specific type.

example:

type Base is tagged record ... end record;
type PBase is access Base;
type CBase is access Base'Class;

type Derived is new Base with record ... end record;
type PDerived is access Derived;
type CDerived is access Derived'Class;

procedure Free is new Ada.Unchecked_Deallocation(Base,PBase);
procedure Free is new Ada.Unchecked_Deallocation(Derived,PDerived);

procedure Dispose(self: in out CBase) is
begin
   --?
   self := null;
end Dispose;

procedure Dispose(self: in out CDerived) is
begin
    -- ?
   self := null;
end Dispose;

declare
    B: CBase := new Base;
    D: CBase := new Derived;
begin
    Dispose(B);
    Dispose(D);
end;

I want both Disposes to work as they should, what should I fill them with?

Zygfryd





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

* Re: virtual destructors
  2003-04-22 14:56   ` kat-Zygfryd
@ 2003-04-22 15:45     ` kat-Zygfryd
  2003-04-22 16:34       ` tmoran
                         ` (2 more replies)
  2003-04-22 17:33     ` virtual destructors Matthew Heaney
  1 sibling, 3 replies; 17+ messages in thread
From: kat-Zygfryd @ 2003-04-22 15:45 UTC (permalink / raw)


Never mind, I didn;t thinf of directly declaring

procedure Free is new Ada.Unchecked_Deallocation(Base'Class,CBase);
procedure Free is new Ada.Unchecked_Deallocation(Derived'Class,CDerived);

Another question: are there any advantages in using
Ada.Finalization for objects that will always be dynamically
allocated/deallocated over simply declaring a Dispose procedure,
with frees object's components before freeing itself?

Zygfryd





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

* Re: virtual destructors
  2003-04-22 15:45     ` kat-Zygfryd
@ 2003-04-22 16:34       ` tmoran
  2003-04-22 21:32         ` Robert A Duff
  2003-04-22 17:18       ` Stephen Leake
  2003-04-22 17:31       ` virtual destructors - doesn't seem to work kat-Zygfryd
  2 siblings, 1 reply; 17+ messages in thread
From: tmoran @ 2003-04-22 16:34 UTC (permalink / raw)


> Another question: are there any advantages in using
> Ada.Finalization for objects that will always be dynamically
> allocated/deallocated over simply declaring a Dispose procedure,
The compiler will make sure Finalize is called, whereas the programmer
will sooner or later forget to call Dispose.



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

* Re: virtual destructors
  2003-04-22 17:18       ` Stephen Leake
@ 2003-04-22 16:34         ` Simon Wright
  2003-04-22 19:57           ` Stephen Leake
  2003-04-23 15:16         ` Matthew Heaney
  1 sibling, 1 reply; 17+ messages in thread
From: Simon Wright @ 2003-04-22 16:34 UTC (permalink / raw)


Stephen Leake <Stephe.Leake@nasa.gov> writes:

> You also need to ensure that both access types use the same storage
> pool. Something like:
> 
> for CDerived'Storage_Pool use CBase'Storage_Pool.

I don't see why? there was no attempt I could see to convert between
the classwide pointer types?



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

* Re: virtual destructors
  2003-04-22 15:45     ` kat-Zygfryd
  2003-04-22 16:34       ` tmoran
@ 2003-04-22 17:18       ` Stephen Leake
  2003-04-22 16:34         ` Simon Wright
  2003-04-23 15:16         ` Matthew Heaney
  2003-04-22 17:31       ` virtual destructors - doesn't seem to work kat-Zygfryd
  2 siblings, 2 replies; 17+ messages in thread
From: Stephen Leake @ 2003-04-22 17:18 UTC (permalink / raw)


"kat-Zygfryd" <6667@wp.pl> writes:

> Never mind, I didn;t thinf of directly declaring
> 
> procedure Free is new Ada.Unchecked_Deallocation(Base'Class,CBase);
> procedure Free is new Ada.Unchecked_Deallocation(Derived'Class,CDerived);

You also need to ensure that both access types use the same storage
pool. Something like:

for CDerived'Storage_Pool use CBase'Storage_Pool.

> Another question: are there any advantages in using Ada.Finalization
> for objects that will always be dynamically allocated/deallocated
> over simply declaring a Dispose procedure, with frees object's
> components before freeing itself?

Yes. The compiler ensures that Finalize is called. Users will forget
to call Dispose.

-- 
-- Stephe



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

* Re: virtual destructors
  2003-04-22 14:18 virtual destructors kat-Zygfryd
  2003-04-22 14:27 ` Stephen Leake
@ 2003-04-22 17:28 ` Matthew Heaney
  2003-04-22 17:40   ` kat-Zygfryd
  1 sibling, 1 reply; 17+ messages in thread
From: Matthew Heaney @ 2003-04-22 17:28 UTC (permalink / raw)


"kat-Zygfryd" <6667@wp.pl> wrote in message news:<b83ivk$29l$1@news.onet.pl>...
> How can I define a virtual destructor in Ada95?

There are two ways.

I. Use controlled types

Have your type (privately) derived from Controlled, and then use
Unchecked_Deallocation to delete it through a class-wide type:

package P is

   type T is tagged private;

   type T_Class_Access is access all T'Class;

   procedure Op (O : access T);

private

   type T is new Controlled with record
      ...;
   end record;

   procedure Finalize (O : in out T);

end P;


package P.C is

   type NT is new T with private;

private

   type NT is new T with record
      ...;
   end record;

   procedure Finalize (O : in out NT);

end P.C;

procedure Free is 
  new Ada.Unchecked_Deallocation (T'Class, T_Class_Access);

declare
   O1 : T_Class_Access := new T;
   O2 : T_Class_Access := new NT;
begin
   Free (O1);  --call P.Finalize
   Free (O2);  --call P.C.Finalize
end;


What's happening here is that the Ada run-time system knows that types
in T'Class are controlled, so that when you use
Unchecked_Deallocation, it calls the Finalize operation for the object
being deleted.

So in this sense destructors are already dispatching in Ada95, and
there's nothing special you need to do.

Note that Finalize operations for a class are typically implemented by
performing actions specific to the derived type, and then forwarding
the call to the parent type, e.g.

procedure Finalize (O : in out NT) is
begin
  --do NT stuff here
  Finalize (T (O)); --"view conversion" to call T's Finalize
end;

Also note that if any components are controlled, they too will get
finalized in the normal way.  For example, if we had implemented T
this way:

private
  type T is tagged record -- not itself controlled
     Vector : Vector_Subtype;
  end record;

Here, the Vector_Subtype is an instance of
Charles.Vectors.Unbounded.Container_Type, which is implemented as a
controlled type.  So when an object of T is deallocated, controlled
finalization of its component(s) occurs, which means here that the
Finalize for Vector is called automatically.

What this really means is that you may not need a virtual destructor
at all.


II. Use an explicit dispatching destructor

In this case you're going to assume some of the duties yourself, by
explicitly calling a dispatching operation.

What many Ada programmers don't seem to realize is that operations
that have access parameters are primitive for a type, meaning that
they are inherited during derivations, and (more importantly here)
dispatch when called with a parameter whose type is class-wide.

Let's modify our class above to add a private primitive operation:

package P is
   type T (<>) is tagged limited private;
   type T_Class_Access is access all T'Class;
   function New_T return T_Class_Access;
   procedure Free (O : in out T_Class_Access);
private
   type T is tagged limited record ...;
   procedure Do_Free (O : access T); --declare primitive
end P;

package P.C is
  type NT (<>) is new T with private;
  function New_NT return T_Class_Access;
private
  type NT is new T with record ...;
  procedure Do_Free (O : access NT); --override primitive
end P.C;

What we want to do is hand off the pointer to the object to the
destructor, but we need to the destructor to dispatch.  The public
Free operation is implemented this way:

procedure Free (O : in out T_Class_Access) is
begin
  if O /= null then
     Do_Free (O);  -- dispatches 
     O := null;
  end if;
end Free;

The object designated by pointer O has type T'Class, which means that
if called with a primitive operation, then dispatching will occur. 
Do_Free is primitive, so it dispatches.  For example:

declare
  O1 : T_Class_Access := New_T;
  O2 : T_Class_Access := New_NT;
begin
  Free (O1); --internal dispatch to T's Do_Free
  Free (O2); --internal dispatch to NT's Do_Free
end;

The Free operation is an example of the "template method" pattern. 
The Do_Free operation is the "virtual destructor."



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

* virtual destructors - doesn't seem to work
  2003-04-22 15:45     ` kat-Zygfryd
  2003-04-22 16:34       ` tmoran
  2003-04-22 17:18       ` Stephen Leake
@ 2003-04-22 17:31       ` kat-Zygfryd
  2003-04-22 17:32         ` Simon Wright
  2 siblings, 1 reply; 17+ messages in thread
From: kat-Zygfryd @ 2003-04-22 17:31 UTC (permalink / raw)


It doesn't seem to work :(
Look:

-- errata to previous code
type CBase is access all Base'Class;
type CDerived is access all Derived'Class;
-- /errata

procedure Dispose(self: in out CBase) is
begin
    Put_Line("CBase.Dispose");
end Dispose;

procedure Dispose(self: in out CDerived) is
begin
    Put_Line("CDerived.Dispose");
end Dispose;

function create_derived return CDerived is
begin
    return new Derived;
end create_derived;

declare
    B: CBase := CBase(create_derived);
begin
    Dispose(B); -- outputs "CBase.Dispose"
end;

what am I doing wrong?

Zygfryd





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

* Re: virtual destructors - doesn't seem to work
  2003-04-22 17:31       ` virtual destructors - doesn't seem to work kat-Zygfryd
@ 2003-04-22 17:32         ` Simon Wright
  0 siblings, 0 replies; 17+ messages in thread
From: Simon Wright @ 2003-04-22 17:32 UTC (permalink / raw)


"kat-Zygfryd" <6667@wp.pl> writes:

> It doesn't seem to work :(
> Look:
> 
> -- errata to previous code
> type CBase is access all Base'Class;
> type CDerived is access all Derived'Class;
> -- /errata
> 
> procedure Dispose(self: in out CBase) is
> begin
>     Put_Line("CBase.Dispose");
> end Dispose;
> 
> procedure Dispose(self: in out CDerived) is
> begin
>     Put_Line("CDerived.Dispose");
> end Dispose;
> 
> function create_derived return CDerived is
> begin
>     return new Derived;
> end create_derived;
> 
> declare
>     B: CBase := CBase(create_derived);
> begin
>     Dispose(B); -- outputs "CBase.Dispose"
> end;
> 
> what am I doing wrong?

Your Dispose operations aren't dispatching operations (they take a
parameter of a type which you have declared, not an anonymous
access-to-tagged-type).

So when you say Dispose(B); it is Dispose(self: in out CBase) that
gets called.

type T is tagged private;
type T_P is access T;
type T_C is access T'Class;

procedure P1 (P : T);          --  dispatches
procedure P2 (P : access T);   --  dispatches
procedure P3 (P : T_P);        --  doesn't dispatch
procedure P4 (P : T_C);        --  doesn't dispatch


I'm a bit puzzled by what you're trying to do. I would have expected
your procedure Dispose(self: in out CDerived) to need to call your
procedure Dispose(self: in out CBase) (because a Derived is a Base and
the Base part will need finalizing).

I would have thought what you'd really like to do is have just the one
classwide pointer type CBase and have the correct finalization
called. Matt has shown how to do that .. having two classwide pointer
types seems likely to cause trouble.



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

* Re: virtual destructors
  2003-04-22 14:56   ` kat-Zygfryd
  2003-04-22 15:45     ` kat-Zygfryd
@ 2003-04-22 17:33     ` Matthew Heaney
  1 sibling, 0 replies; 17+ messages in thread
From: Matthew Heaney @ 2003-04-22 17:33 UTC (permalink / raw)


"kat-Zygfryd" <6667@wp.pl> wrote in message news:<b83l69$7bk$1@news.onet.pl>...
>
> I want to have destructors working on access' to class wide types,
> so that when passed a variable, an actual type destructor was
> called, not a one overloaded for the specific type.
> 
> example:
> 
> type Base is tagged record ... end record;
> type PBase is access Base;
> type CBase is access Base'Class;
> 
> type Derived is new Base with record ... end record;
> type PDerived is access Derived;
> type CDerived is access Derived'Class;
> 
> procedure Free is new Ada.Unchecked_Deallocation(Base,PBase);
> procedure Free is new Ada.Unchecked_Deallocation(Derived,PDerived);
> 
> procedure Dispose(self: in out CBase) is
> begin
>    --?
>    self := null;
> end Dispose;
> 
> procedure Dispose(self: in out CDerived) is
> begin
>     -- ?
>    self := null;
> end Dispose;
> 
> declare
>     B: CBase := new Base;
>     D: CBase := new Derived;
> begin
>     Dispose(B);
>     Dispose(D);
> end;
> 
> I want both Disposes to work as they should, what should I fill them with?

Give the class a primitive operation that accepts an access parameter:

procedure Do_Dispose (B : access Base) is ...;
procedure Do_Dispose (D : access Derived) is ...;

procedure Dispose (B : in out CBase) is
begin
   if B /= null then
      Do_Dispose (B);  --dispatches
      B := null;
   end if;
end Dispose;



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

* Re: virtual destructors
  2003-04-22 17:28 ` Matthew Heaney
@ 2003-04-22 17:40   ` kat-Zygfryd
  0 siblings, 0 replies; 17+ messages in thread
From: kat-Zygfryd @ 2003-04-22 17:40 UTC (permalink / raw)


"Matthew Heaney" <mheaney@on2.com> wrote in message
news:1ec946d1.0304220928.72c2acc8@posting.google.com...
> "kat-Zygfryd" <6667@wp.pl> wrote in message
news:<b83ivk$29l$1@news.onet.pl>...
> > How can I define a virtual destructor in Ada95?
>
> There are two ways.
>
> I. Use controlled types
>
> Have your type (privately) derived from Controlled, and then use
> Unchecked_Deallocation to delete it through a class-wide type:
>
> package P is
>
>    type T is tagged private;
>
>    type T_Class_Access is access all T'Class;
>
>    procedure Op (O : access T);
>
> private
>
>    type T is new Controlled with record
>       ...;
>    end record;
>
>    procedure Finalize (O : in out T);
>
> end P;
>
>
> package P.C is
>
>    type NT is new T with private;
>
> private
>
>    type NT is new T with record
>       ...;
>    end record;
>
>    procedure Finalize (O : in out NT);
>
> end P.C;
>
> procedure Free is
>   new Ada.Unchecked_Deallocation (T'Class, T_Class_Access);
>
> declare
>    O1 : T_Class_Access := new T;
>    O2 : T_Class_Access := new NT;
> begin
>    Free (O1);  --call P.Finalize
>    Free (O2);  --call P.C.Finalize
> end;
>
>
> What's happening here is that the Ada run-time system knows that types
> in T'Class are controlled, so that when you use
> Unchecked_Deallocation, it calls the Finalize operation for the object
> being deleted.
>
> So in this sense destructors are already dispatching in Ada95, and
> there's nothing special you need to do.
>
> Note that Finalize operations for a class are typically implemented by
> performing actions specific to the derived type, and then forwarding
> the call to the parent type, e.g.
>
> procedure Finalize (O : in out NT) is
> begin
>   --do NT stuff here
>   Finalize (T (O)); --"view conversion" to call T's Finalize
> end;

Thanks, I like that :) Hope it'll work for me

Zygfryd






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

* Re: virtual destructors
  2003-04-22 16:34         ` Simon Wright
@ 2003-04-22 19:57           ` Stephen Leake
  2003-04-22 20:19             ` Simon Wright
  2003-04-22 21:23             ` Robert A Duff
  0 siblings, 2 replies; 17+ messages in thread
From: Stephen Leake @ 2003-04-22 19:57 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Stephen Leake <Stephe.Leake@nasa.gov> writes:
> 
> > You also need to ensure that both access types use the same storage
> > pool. Something like:
> > 
> > for CDerived'Storage_Pool use CBase'Storage_Pool.
> 
> I don't see why? there was no attempt I could see to convert between
> the classwide pointer types?

In general, the compiler can use different storage pools for each
access type. 

If you do:

A : CBase := new Derived'();

and then later:

Free (A);

The compiler might allocation from CDerived_Storage_Pool, and then
deallocate from CBase_Storage_Pool. Very bad. 

-- 
-- Stephe



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

* Re: virtual destructors
  2003-04-22 19:57           ` Stephen Leake
@ 2003-04-22 20:19             ` Simon Wright
  2003-04-22 21:23             ` Robert A Duff
  1 sibling, 0 replies; 17+ messages in thread
From: Simon Wright @ 2003-04-22 20:19 UTC (permalink / raw)


Stephen Leake <Stephe.Leake@nasa.gov> writes:

> Simon Wright <simon@pushface.org> writes:
> 
> > Stephen Leake <Stephe.Leake@nasa.gov> writes:
> > 
> > > You also need to ensure that both access types use the same storage
> > > pool. Something like:
> > > 
> > > for CDerived'Storage_Pool use CBase'Storage_Pool.
> > 
> > I don't see why? there was no attempt I could see to convert between
> > the classwide pointer types?
> 
> In general, the compiler can use different storage pools for each
> access type. 
> 
> If you do:
> 
> A : CBase := new Derived'();
> 
> and then later:
> 
> Free (A);
> 
> The compiler might allocation from CDerived_Storage_Pool, and then
> deallocate from CBase_Storage_Pool. Very bad. 

Indeed, I hadn't spotted that particular problem (I was looking at the
procedures, not the main program). Sorry.



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

* Re: virtual destructors
  2003-04-22 19:57           ` Stephen Leake
  2003-04-22 20:19             ` Simon Wright
@ 2003-04-22 21:23             ` Robert A Duff
  1 sibling, 0 replies; 17+ messages in thread
From: Robert A Duff @ 2003-04-22 21:23 UTC (permalink / raw)


Stephen Leake <Stephe.Leake@nasa.gov> writes:

> In general, the compiler can use different storage pools for each
> access type. 

True, but in the following example, there is only one access type:
CBase.  So both the "new" and the "Free" will be referring to the same
storage pool, namely CBase'Storage_Pool, so all is well.

> If you do:
> 
> A : CBase := new Derived'();
> 
> and then later:
> 
> Free (A);
> 
> The compiler might allocation from CDerived_Storage_Pool, and then
> deallocate from CBase_Storage_Pool. Very bad. 

To get in trouble, you have to do a type conversion.

- Bob



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

* Re: virtual destructors
  2003-04-22 16:34       ` tmoran
@ 2003-04-22 21:32         ` Robert A Duff
  0 siblings, 0 replies; 17+ messages in thread
From: Robert A Duff @ 2003-04-22 21:32 UTC (permalink / raw)


tmoran@acm.org writes:

> > Another question: are there any advantages in using
> > Ada.Finalization for objects that will always be dynamically
> > allocated/deallocated over simply declaring a Dispose procedure,
> The compiler will make sure Finalize is called, whereas the programmer
> will sooner or later forget to call Dispose.

But the Finalize is just doing some Unchecked_Deallocations (according
to the OP), so it doesn't really matter.  If you forget to Dispose,
then it will Dispose just before program exit, which is not really
useful.

If the Finalize were doing something important, then yes, the Ada
implementation makes sure it happens.  But for library-level access
types (which is 99.9% of all access types, I suspect), it happens very
late in the game if you don't explicitly Dispose.

I think the truth is that finalization is much more useful for stack
objects than for heap objects.  In Java, where everything's a heap
object, and deallocation is done by GC, finalization (quite a complex
feature) is nigh unto useless, which is rather a shame.  You can't do
most of the useful tricks that Ada and C++ allow, like locking/unlocking
a resource via finalization.

- Bob



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

* Re: virtual destructors
  2003-04-22 17:18       ` Stephen Leake
  2003-04-22 16:34         ` Simon Wright
@ 2003-04-23 15:16         ` Matthew Heaney
  1 sibling, 0 replies; 17+ messages in thread
From: Matthew Heaney @ 2003-04-23 15:16 UTC (permalink / raw)


Stephen Leake <Stephe.Leake@nasa.gov> wrote in message news:<u3ckacuwv.fsf@nasa.gov>...
> "kat-Zygfryd" <6667@wp.pl> writes:
> 
> Yes. The compiler ensures that Finalize is called. Users will forget
> to call Dispose.

Another possibility is to use a handle of some kind (a la the C++
auto_ptr class), that claims ownership of the access object, and
automatically calls Free when the handle object is itself finalized.

The Charles library has an Access_Control package that does just that,
e.g.

declare
   P1 : Pointer_Type; --from Charles.Access_Control
   P2 : Pointer_Type;
begin
   Initialize (P1, new T); --claim ownership
   Assign (Target => P2, Source => P1); --transfer ownership
   Op (+P2); --use access object
end; --P2 will Free object

You can even use this in a factory function:

function New_T return T_Access is
   P : Pointer_Type;
begin
   Initialize (P, new T); --claim ownership
   --do some stuff that may raise an exception
   return Release (P); --relinguish ownership
end;

If the factory function New_T raises an exception prior to reaching
the return, then pointer P will free the allocated object during its
finalization, because it still owns the object.

If we do reach the return statement, then we tell P to release the
object, so P does nothing during its finalization, and ownership of
the allocated object is transfered to the caller of New_T.

The party to whom New_T transfers ownership might indeed even be
another access control object:

declare
   P : Pointer_Type;
begin
   Initialize (P, Value => New_T);
   --now use +P
end; --free object during finalization of P

The Charles.Access_Control component is part of the Charles library,
available at my website:

http://home.earthlink.net/~matthewjheaney/charles/



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

end of thread, other threads:[~2003-04-23 15:16 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-22 14:18 virtual destructors kat-Zygfryd
2003-04-22 14:27 ` Stephen Leake
2003-04-22 14:56   ` kat-Zygfryd
2003-04-22 15:45     ` kat-Zygfryd
2003-04-22 16:34       ` tmoran
2003-04-22 21:32         ` Robert A Duff
2003-04-22 17:18       ` Stephen Leake
2003-04-22 16:34         ` Simon Wright
2003-04-22 19:57           ` Stephen Leake
2003-04-22 20:19             ` Simon Wright
2003-04-22 21:23             ` Robert A Duff
2003-04-23 15:16         ` Matthew Heaney
2003-04-22 17:31       ` virtual destructors - doesn't seem to work kat-Zygfryd
2003-04-22 17:32         ` Simon Wright
2003-04-22 17:33     ` virtual destructors Matthew Heaney
2003-04-22 17:28 ` Matthew Heaney
2003-04-22 17:40   ` kat-Zygfryd

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