comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Generics with concrete and class-wide types
Date: Mon, 31 Mar 2008 16:38:41 -0700 (PDT)
Date: 2008-03-31T16:38:41-07:00	[thread overview]
Message-ID: <f0879dc0-7498-48f7-8d44-9856316d35ce@s19g2000prg.googlegroups.com> (raw)
In-Reply-To: 279b6f4f-36cf-446f-8b54-fd72b957b22f@i7g2000prf.googlegroups.com

On Mar 31, 1:22 pm, Maciej Sobczak <see.my.homep...@gmail.com> wrote:

> Consider a generic subprogram that makes sense for arguments of both
> class-wide type and a concrete type.

[snip]

> Now, the generic subprogram that operates on the given iterator,
> *without* using dynamic dispatch, can have the following form:
>
> generic
>   type Element is private;
>   type Iterator_Type (<>) is private;
>   with function Get (I : Iterator_Type) return Element is <>;
>   -- and so on for all other operations that are needed by this
> subprogram
> procedure Some_Procedure (I : in Iterator_Type);
>
> This works fine for direct instantiation with My_Concrete_Iterator:
>
> procedure SP is new Some_Procedure
>   (T => Integer, Iterator_Type => My_Concrete_Iterator);
>
> The problem is that I failed to instantiate Some_Procedure for
> Iterator_Integer.Iterator'Class, which I could then reuse for
> My_Concrete_Iterator as well as for My_Other_Concrete_Iterator and so
> on:
>
> -- does not compile:
> procedure SP is new Some_Procedure
>   (T => Integer, Iterator_Type => Iterator_Integer'Class); -- Bang!
>
> Bang, because relevant iterator operations cannot be found - the ones
> that are found have *wrong signatures*.

[snip]

At first, I thought it might be possible to do this, without
duplicating code, by writing a second generic package specifically for
class-wide types that would instantiate Some_Procedure.  Something
like this:

    generic
        type Element is private;
        type Iterator_Root is tagged private;
        with function Get (I : in Iterator_Root) return Element is <>;
        ... other operations
    package SP_For_Class is
        procedure Some_Procedure_Class (I : in Iterator_Root'Class);
    end SP_For_Class;

    with Some_Procedure;
    package body SP_For_Class is
        function Dispatching_Get (I : in Iterator_Root'Class)
                    return Element is
        begin
            return Get (I);
        end Dispatching_Get;
        ... similarly for other operations
        procedure SP_Inst is new Some_Procedure
            (Element, Iterator_Root'Class,
             Dispatching_Get, ...other operations);
        procedure Some_Procedure_Class (I : in Iterator_Root'Class)
            renames SP_Inst;
    end SP_For_Class;

Then for a concrete type, the programmer would instantiate
Some_Procedure; for a class-wide type, the programmer would
instantiate SP_For_Class, and then if Inst is the instance,
Inst.Some_Procedure_Class would be the equivalent procedure.
SP_For_Class would be sort of a wrapper, but it wouldn't need to
duplicate any of the logic from Some_Procedure.

The problem I ran into was the line "return Get(I)" fails because Get
is not a primitive operation of Iterator_Root and thus is not seen as
a dispatching operation.

What's missing here is a way to specify a generic formal subprogram
that must be a primitive operation of some tagged type (possibly a
generic formal tagged type), so that in the body of the generic the
formal subprogram will be treated as a dispatching operation; in an
instantiation, of course, the actual subprogram would have to meet the
criterion.  It seems like this might be a useful feature in some
cases besides this one (although I can't think of one offhand), but
I can see how it would be difficult to work this into the syntax.
(Especially if the generic formal subprogram has two different
parameter or result tagged types; you'd need a way to tell it which
type the subprogram must be a primitive operation of.)

(P.S. It seems like we had a discussion on Ada-Comment some years ago
about the sort of issue Maciej mentions, at least with regard to the
"=" function.  Some programmers were writing code, which GNAT accepted
due a bug, where generics declared

  with function "=" (Left, Right : T) is <>;

and then the generic was instantiated with some class-wide type for
T.  It
seemed like there was some sympathy for allowing this or providing for
a capability that would make this work, but not enough sympathy for
anyone to actually do anything about it.  Bob Duff, does this ring a
bell at all?)

                                -- Adam



  reply	other threads:[~2008-03-31 23:38 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-31 20:22 Generics with concrete and class-wide types Maciej Sobczak
2008-03-31 23:38 ` Adam Beneschan [this message]
2008-04-01 20:10   ` Randy Brukardt
2008-04-01 21:17     ` Adam Beneschan
2008-04-01  0:23 ` Randy Brukardt
2008-04-01  3:57   ` Eric Hughes
2008-04-01  6:58     ` christoph.grein
2008-04-01  7:22 ` Georg Bauhaus
2008-04-01  9:42 ` Dmitry A. Kazakov
2008-04-01  9:51   ` Maciej Sobczak
2008-04-01 10:53     ` Dmitry A. Kazakov
replies disabled

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