Heath White ([log in to unmask]) said:

  > One of the main headaches this causes occurs when you already have
  > a tagged hierarchy of types.  You want to derive off from it, but
  > you want the new type to have controlled behavior.  There is no
  > good way to do this.

   Of course there is, but in part it is non-intuitive...

  If you are adding a component that needs to be controlled, the
controlledness is a property of the component, and the language
supports that correctly.  It has to, since you might not be aware that
the component you are adding to a non-controlled class is controlled.

  The more "troubling" case is when the addition of a component
creates a need to finalize the containing structure.  Access
discriminants allow the compontent to see the containing structure.

  I keep meaning to create an abstraction which deals with the most
common sort of such extensions separate from other "building block"
tagged components.  It is less than twenty lines long--but choosing
some of those lines correctly takes thought.  Hmmm...

  with Ada.Finalization;
  generic
    type Uncontrolled(<>) is abstract tagged limited private;
    with procedure Finalize(Object: in out Uncontrolled);
  package Add_Finalization is
    type Controlled is new Uncontrolled with private;
  private
    type Component(Parent: access Controlled) is new
       Ada.Finalization.Limited_Controlled with null record;
    type Controlled is new Uncontrolled with record
       Controller: Component(Controlled'Access); end record;
    procedure Finalize(Object: in out Component);
  end Add_Finalization;

  package body Add_Finalization is
    procedure Finalize(Object: in out Component) is
    begin Finalize(Uncontrolled(Object.Parent.all));
    end Finalize;
  end Add_Finalization;

  (Untested, but compiled, code. Comments and improvements welcome.)

  This version has the side effect of making the extended type
limited.  The body for a non-limited version is much more complex
because you have to use record with an access value as a
non-discriminant, then track assignment and copying using Intialize
and Adjust.  (Left as an exercise for the reader.)

  There is however one "can't be avoided" problem.  The order in which
the finalization of two extensions will be called is determined in
part by the subclassing order (see 7.6.1(9)) and in part by whether or
not there is an access discriminant.  If you have too many components
trying to finalize things, the ordering can get to be a problem.


                                        Robert I. Eachus

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