comp.lang.ada
 help / color / mirror / Atom feed
* Re: Generic package problem
@ 1993-07-29  3:10 Gene Ouye
  0 siblings, 0 replies; only message in thread
From: Gene Ouye @ 1993-07-29  3:10 UTC (permalink / raw)


Charles Lindsey (chl@clw.cs.man.ac.uk) wrote:

: Please can someone explain hte following. I am using AdaEd.

: I have a generic package 'linked_lists' which does what you would expect, and
: takes one TYPE parameter known as 'ANYTHING'.

: I have another package which publishes an abstract data type 'line'. I also
: wanted clients of this package to be able to use linked lists of lines. So I
: wrote:

: WITH linked_lists;
: PACKAGE lines IS
:   TYPE line is PRIVATE;
:   PACKAGE line_lists IS NEW linked_lists(line);
: PRIVATE
:   etc.

: and the compiler complained, after the package instantiation line,

: *** ERROR: Invalid use of private type in instantiation of ANYTHING (RM 12.3)

: Now I can well understand why a compiler might find difficulty in handling
: this, and hence why it might be forbidden, but I have read TFRM (esp. 12.3
: thereof), and I cannot see exactly where this is forbidden (it is certainly
: OK by the visibility rules). Please can someone enlighten me?

Take a look at LRM 7.4.1, paragraphs 4 and 6.

7.4.1(4) (excerpted):

    Within the specification of a package that declares a private type
    and before the end of the corresponding full type declaration, a
    restriction applies to the use of the name that denotes the private
    type...  The only allowed occurrences of such a name are in a deferred
    constant declaration, a type or subtype declaration, a subprogram
    specification, or an entry declaration;...

7.4.1(6) (excerpted) (this paragraph is part of the Notes for 7.4.1):

    ...before the full declaration, the name of the private type cannot
    be used in a generic instantiation...

: Of course, by moving the package instantiation after the real declaration of
: 'line' in the PRIVATE part it accepted it. But what should I do if I really
: want the package line_lists to be visible to the clients of 'lines', but
: also within the PRIVATE part of lines (some of the record fields in the
: PRIVATE part are of type line_lists.linked_list)? Do I have to instantiate
: it twice, and if so will the types exported by the two instantiations really
: be compatible?

If you instantiate it twice, the types exported from the instantiations
will not be compatible (if you're using the word the way I think you
are).  That is, the two instantiations are different packages and any
types or objects they export will also be different.  You could always
force a conversion between the two types via Unchecked_Conversion, but
this will get ugly and will force you to add a lot of with's that will
clutter up your architecture.

I can't see what else you have in your packages, and I'm not sure how
you intend them to be used, but I wonder if you have properly separated
the behaviors of Line from the behaviors of a collection of Lines.  I
don't mean this as a criticism of your design, it's just the first
question I would ask myself in this situation.

If you really do need visibility to the Line_Lists instantiation in the
private (or non-visible) part of the Lines package, could it be
rearranged so that you only need visibility in the body of Lines?  If
so, then Line_Lists could be a library level instantiation that could be
with'ed by the body of Lines.

Personally, I think what follows is really ugly, but it will do the
trick if it's what you need.  There is an assumption here that AdaEd
will allow the spec/body with'ing games that I play here with the
generic instantiation (I don't have access to AdaEd so I can't try it
out).

-- I assume Linked_Lists looks something like this:
generic
    type Anything is private; -- this is the type of an element in the lists
package Linked_Lists is

    type Linked_List is private;

    -- need operations on linked lists, such as:
    procedure Add (Item : in Anything; To_List : in out Linked_List);

    -- there should also be constructors, destructors, etc.

private
    type Linked_List is access Anything;
end Linked_Lists;
                 
-- of course, it has a body, too.
package body Linked_Lists is
    procedure Add (Item : in Anything; To_List : in out Linked_List) is
    begin
        null; -- this should be code to add another item to the list
    end Add;
end Linked_Lists;
                                                   

-- Note: the Linked_List dependency is no longer here.
package Lines is

    type Line is private;

    -- need operations that do things to a line

private  
    type Some_Strange_Incomplete_Type;
    type Some_Strange_Access_Type is access Some_Strange_Incomplete_Type;
    type Line is
        record
            Text             : String (1 .. 80);
            Some_Other_Field : Some_Strange_Access_Type;
        end record;
end Lines;


-- Now we instantiate the generic as a library unit with the Line type
-- declared in the Lines package.
with Linked_Lists;
with Lines;
package Line_Lists is new Linked_Lists (Anything => Lines.Line);
                                 

-- Finally, we complete the body of the Lines package with the instantiation.
with Line_Lists;
package body Lines is
    type Some_Strange_Incomplete_Type is access Line_Lists.Linked_List;

    -- now you implement your package body and do whatever you need
    -- with the Linked_List and the Line.

end Lines;

========================================================================

Like I said, I think this particular example is really ugly, but I know
of instances when it has to be done (I don't think this is one of those
instances).  I suspect that your abstraction of Line is broken if it
needs access to a list of Lines.
                                                      
If you want to discuss this further, feel free to send me e-mail.

Gene Ouye (geneo@rational.com)   Rational, Bethesda, MD, USA
(301) 897-4014

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~1993-07-29  3:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1993-07-29  3:10 Generic package problem Gene Ouye

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