comp.lang.ada
 help / color / mirror / Atom feed
* Access to function returning class-wide type
@ 2008-08-21 10:13 Paweł 'Nivertius' Płazieński
  2008-08-21 10:33 ` Paweł 'Nivertius' Płazieński
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 10:13 UTC (permalink / raw)


Hello all.

I'm new here, but I'll try to stick on.

Let me start with a tricky problem:

Consider following code:

----------------------------------------

package A is 
        type Abstracted is abstract tagged null record;
        function Proc (N : Natural) return Abstracted is abstract;

        type The_Access_Type is access function (N : Natural) return
Abstracted'Class;

end A;

-- package A body ommited;

with A;
package B is 
        type Derived is new A.Abstracted with null record;
        function Proc (N : Natural) return Derived;

        Failing_Object : A.The_Access_Type := B.Proc'Access;
        --  will not compile, error: 'expected type The_Access_Type / found type
access function Proc defined at ...'

        function Proc_Wrapper (N : Natural) return Abstracted'Class;

        Working_Object : A.The_Access_Type := B.Proc_Wrapper'Access;
        -- compiler doesn't complain

end B;

package B body is
        function Proc_Wrapper (N : Natural) return Abstracted'Class is
        begin
                return Abstracted'Class'(Proc (N));
        end Proc;

        -- function Proc body ommited
end B;

----------------------------------------

What I need is a access type to 'constructor' of an derivate of abstract
object.
As I presented, there is a workaround, but that's not the 'right' way to do
it. I really want to do it without some tricky wrapping.
How do I define The_Access_Type to do what I want?

Thanks in advance.

-- 
Paweł Płazieński aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 10:13 Access to function returning class-wide type Paweł 'Nivertius' Płazieński
@ 2008-08-21 10:33 ` Paweł 'Nivertius' Płazieński
  2008-08-21 11:02 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 10:33 UTC (permalink / raw)


Little correction:

>         function Proc_Wrapper (N : Natural) return Abstracted'Class is
>         begin
>                 return Abstracted'Class'(Proc (N));
>         end Proc;

Proc_Wrapper should return Derived'(Proc(N)); to workaround to work, but it
doesn't really change the problem.

-- 
Paweł Płazieński aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 10:13 Access to function returning class-wide type Paweł 'Nivertius' Płazieński
  2008-08-21 10:33 ` Paweł 'Nivertius' Płazieński
@ 2008-08-21 11:02 ` Dmitry A. Kazakov
  2008-08-21 11:56   ` Paweł 'Nivertius' Płazieński
  2008-08-21 12:01 ` Georg Bauhaus
  2008-08-21 17:02 ` Adam Beneschan
  3 siblings, 1 reply; 15+ messages in thread
From: Dmitry A. Kazakov @ 2008-08-21 11:02 UTC (permalink / raw)


On Thu, 21 Aug 2008 12:13:10 +0200, Pawe� 'Nivertius' P�azie�ski wrote:

> What I need is a access type to 'constructor' of an derivate of abstract
> object.
> As I presented, there is a workaround, but that's not the 'right' way to do
> it. I really want to do it without some tricky wrapping.
> How do I define The_Access_Type to do what I want?

See Ada.Tags.Generic_Dispatching_Constructor. It gives you a function
constructing an object from the type tag, the parameters (Natural in your
case) using the function you want (Proc). It goes as follows:

with Ada.Tags.Generic_Dispatching_Constructor;
package A is 
   type Abstracted is abstract tagged null record;
   function Proc (N : not null access Natural)
      return Abstracted is abstract;
   function Constructor is
      new Ada.Tags.Generic_Dispatching_Constructor
             (Abstracted, Natural, Proc);
end A;

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Access to function returning class-wide type
  2008-08-21 11:02 ` Dmitry A. Kazakov
@ 2008-08-21 11:56   ` Paweł 'Nivertius' Płazieński
  2008-08-21 13:34     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 11:56 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

>> What I need is a access type to 'constructor' of an derivate of abstract
>> object.
>> As I presented, there is a workaround, but that's not the 'right' way to
>> do it. I really want to do it without some tricky wrapping.
>> How do I define The_Access_Type to do what I want?
> See Ada.Tags.Generic_Dispatching_Constructor. It gives you a function
> constructing an object from the type tag, the parameters (Natural in your
> case) using the function you want (Proc). It goes as follows:
> 
> with Ada.Tags.Generic_Dispatching_Constructor;
> package A is
>    type Abstracted is abstract tagged null record;
>    function Proc (N : not null access Natural)
>       return Abstracted is abstract;
>    function Constructor is
>       new Ada.Tags.Generic_Dispatching_Constructor
>              (Abstracted, Natural, Proc);
> end A;

I belive that would work too, but at the cost of defining function Proc (N :
not null access Natural) return ... for each descendant type. That would be
another wrapper, so it's the same resolution to the problem as Proc_Wrapper
in my original code, assuming that I need Proc (N : Natural) as well.

Tell me that I'm wrong, please ;-)

-- 
Paweł Płazieński aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 10:13 Access to function returning class-wide type Paweł 'Nivertius' Płazieński
  2008-08-21 10:33 ` Paweł 'Nivertius' Płazieński
  2008-08-21 11:02 ` Dmitry A. Kazakov
@ 2008-08-21 12:01 ` Georg Bauhaus
  2008-08-21 13:01   ` Paweł 'Nivertius' Płazieński
  2008-08-21 17:02 ` Adam Beneschan
  3 siblings, 1 reply; 15+ messages in thread
From: Georg Bauhaus @ 2008-08-21 12:01 UTC (permalink / raw)


Paweł 'Nivertius' Płazieński schrieb:

> package B is 
>         type Derived is new A.Abstracted with null record;
>         function Proc (N : Natural) return Derived;
> 
>         Failing_Object : A.The_Access_Type := B.Proc'Access;
>         --  will not compile, error: 'expected type The_Access_Type / found type
> access function Proc defined at ...'

(Compiler is right because the profile of B.Proc is different
from that of The_Access_Type (whose functions return Abstracted'Class,
not Derived)

In general, public access types lead to unneccessary complication;
tagged types are by reference already, so you could simply use
dispatching and a factory instead. Do you have spefific needs
for pointers to functions returning by-reference objects?

Or follow Dmitry's advice.


   package A is
      type Abstracted is abstract tagged null record;
      function Proc (N : Natural) return Abstracted is abstract;

      package Constructor is
         No_Suitable_Type: exception;

         function Proc_Wrapper(N : Natural) return Abstracted'Class;
         -- create objects of types in Abstracted'Class; the
         -- specific type depends on N and other things that are
         -- in scope in Constructor's body
      end Constructor;

   end A;

   with A;
   package B is
      type Derived is new A.Abstracted with null record;
      overriding
      function Proc (N : Natural) return Derived;
   end B;



   package body A is
      package body Constructor is

         function Proc_Wrapper(N : Natural) return Abstracted'Class is
         begin
            if N > 666 then  -- and possibly Some_Other_Condition ...
               declare
                  use B;
               begin
                  return Derived'(Proc(N));
               end;
            else
               --
               -- other cases TBD
               --
               raise No_Suitable_Type;
            end if;
         end Proc_Wrapper;

      end Constructor;
   end A;

   package body B is
      function Proc (N : Natural) return Derived is
      begin
         return Derived'(null record);
      end Proc;
   end B;


HTH
--
Georg Bauhaus
Y A Time Drain  http://www.9toX.de



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

* Re: Access to function returning class-wide type
  2008-08-21 12:01 ` Georg Bauhaus
@ 2008-08-21 13:01   ` Paweł 'Nivertius' Płazieński
  2008-08-21 13:50     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 13:01 UTC (permalink / raw)


Georg Bauhaus wrote:

> Paweł 'Nivertius' Płazieński schrieb:
> 
>> package B is
>>         type Derived is new A.Abstracted with null record;
>>         function Proc (N : Natural) return Derived;
>> 
>>         Failing_Object : A.The_Access_Type := B.Proc'Access;
>>         --  will not compile, error: 'expected type The_Access_Type /
>>         found type
>> access function Proc defined at ...'
> (Compiler is right because the profile of B.Proc is different
> from that of The_Access_Type (whose functions return Abstracted'Class,
> not Derived)

I made a test file:

        package A is
                type Abstracted is range 1 .. 100;
                function Proc (N : Natural) return Abstracted;

                type The_Access_Type is 
                        access function (N : Natural) return Abstracted;
        end A;

        package body A is
                function Proc (N : Natural) return Abstracted is
                begin
                        return Abstracted (N);
                end;
        end A;

        package B is
                subtype Derived is A.Abstracted range 1 .. 10;
                function Proc (N : Natural) return Derived;

                Object : A.The_Access_Type := B.Proc'Access;
        end B;

        package body B is
                function Proc (N : Natural) return Derived is
                begin
                        return Derived (N);
                end;
        end B;

And this also fails to compile:
    20.                 Object : A.The_Access_Type := B.Proc'Access;
                                                       |
        >>> not subtype conformant with declaration at line 6
        >>> return type does not match

So I assume that 'fully-conformant' means that types needs to be _exactly_
the same, not even implicitly conversible. That means that one wrapper or
another is required.

> In general, public access types lead to unneccessary complication;
> tagged types are by reference already, so you could simply use
> dispatching and a factory instead. Do you have spefific needs
> for pointers to functions returning by-reference objects?

Well, that was the example my problem boils down to. In real file the access
type is private within top-level package [in example it was A] and used
internally, not even in child packages.

>          function Proc_Wrapper(N : Natural) return Abstracted'Class is
>          begin
>             if N > 666 then  -- and possibly Some_Other_Condition ...
>                declare
>                   use B;
>                begin
>                   return Derived'(Proc(N));
>                end;
>             else
>                --
>                -- other cases TBD
>                --
>                raise No_Suitable_Type;
>             end if;
>          end Proc_Wrapper;

First of all, the problem with that is, that I couldn't define conditions
and types for them dynamicaly.
Second (of all?), each new Derived type in child, or even remotely other
package needs to be hard-coded into examples package A.

I have a map between condition on an object of some type (in example it
was 'N') and access-to-function which creates the object derived from
Abstracted. I've also got funcion which gets the 'object of some type' and
for each key in the map checks if the condition is true. If so,
calls 'constructor' passing that 'object of some type' and returns its
result. If no condition is true, the function raises an exception.
(I probably should wrote that in original post).

-- 
Paweł Płazieński aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 11:56   ` Paweł 'Nivertius' Płazieński
@ 2008-08-21 13:34     ` Dmitry A. Kazakov
  2008-08-22  4:53       ` Randy Brukardt
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry A. Kazakov @ 2008-08-21 13:34 UTC (permalink / raw)


On Thu, 21 Aug 2008 13:56:35 +0200, Pawe� 'Nivertius' P�azie�ski wrote:

> Dmitry A. Kazakov wrote:
> 
>>> What I need is a access type to 'constructor' of an derivate of abstract
>>> object.
>>> As I presented, there is a workaround, but that's not the 'right' way to
>>> do it. I really want to do it without some tricky wrapping.
>>> How do I define The_Access_Type to do what I want?
>> See Ada.Tags.Generic_Dispatching_Constructor. It gives you a function
>> constructing an object from the type tag, the parameters (Natural in your
>> case) using the function you want (Proc). It goes as follows:
>> 
>> with Ada.Tags.Generic_Dispatching_Constructor;
>> package A is
>>    type Abstracted is abstract tagged null record;
>>    function Proc (N : not null access Natural)
>>       return Abstracted is abstract;
>>    function Constructor is
>>       new Ada.Tags.Generic_Dispatching_Constructor
>>              (Abstracted, Natural, Proc);
>> end A;
> 
> I belive that would work too, but at the cost of defining function Proc (N :
> not null access Natural) return ... for each descendant type.

Yes, it is the body of the "constructor".

> That would be
> another wrapper, so it's the same resolution to the problem as Proc_Wrapper
> in my original code, assuming that I need Proc (N : Natural) as well.

Not really, because it would replace old Proc completely. The idea is:

with Ada.Tags;  use Ada.Tags;
package A is
   type Abstracted is abstract tagged null record;
      -- To be used
   function Factory (T : Tag; N : Natural) return Abstracted'Class;
      -- Implementation detail, to be provided by each derived type
   function Proc (N : not null access Natural)
      return Abstracted is abstract;
end A;

with Ada.Tags.Generic_Dispatching_Constructor;
package body A is 
   function Make_It is
      new Generic_Dispatching_Constructor (Abstracted, Natural, Proc);
   function Factory (T : Tag; N : Natural) return Abstracted'Class is
      Parameters : aliased Natural := N;
   begin
      return Make_It (T, Parameters'Access);
   end Factory;
end A;

Now, when you derive from Abstracted you override Proc and that's all you
need to keep Factory working:

   type Concrete is new Abstracted with private;
   overriding Proc (N : not null access Natural return Concrete;

In short, the solution replaces pointer->constructor with tag->constructor.
Both enforced to be overridden.

P.S. I don't know reasons why it was decided to use an access type in
Ada.Tags.Generic_Dispatching_Constructor profile. One could always pass a
pointer there if a side effect on the parameters were desired. But that is
another issue, and in any case Proc is thought as an implementation detail,
so its exact profile should not really matter.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Access to function returning class-wide type
  2008-08-21 13:01   ` Paweł 'Nivertius' Płazieński
@ 2008-08-21 13:50     ` Dmitry A. Kazakov
  2008-08-21 19:30       ` Paweł 'Nivertius' Płazieński
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry A. Kazakov @ 2008-08-21 13:50 UTC (permalink / raw)


On Thu, 21 Aug 2008 15:01:01 +0200, Pawe� 'Nivertius' P�azie�ski wrote:

> First of all, the problem with that is, that I couldn't define conditions
> and types for them dynamicaly.
> Second (of all?), each new Derived type in child, or even remotely other
> package needs to be hard-coded into examples package A.
> 
> I have a map between condition on an object of some type (in example it
> was 'N') and access-to-function which creates the object derived from
> Abstracted. I've also got funcion which gets the 'object of some type' and
> for each key in the map checks if the condition is true. If so,
> calls 'constructor' passing that 'object of some type' and returns its
> result. If no condition is true, the function raises an exception.
> (I probably should wrote that in original post).

So you could replace it with a map condition->type tag and then proceed
with Ada.Tags.Generic_Dispatching_Constructor, because the map
tag->constructor is for free, here you do not need pointers any more, in
Ada 2005. The compiler will force to override the "constructor" for each
concrete derived type.

-------------
Having said that, there still is a difficult problem with construction of
the map. I don't know if it is an issue for you, but it is for the
persistency layer I designed. The problem is that if the map is open-ended,
you need some mechanism of registration of each new type in the map. This
is still unresolved in Ada. The pattern I am using is that each package
declaring a new type is required to call some class-wide procedure
registering the type upon package elaboration. In your case it is the
condition associated with the type tag. That cannot be enforced, and it
works only at the library level, i.e. for "immortal" types.

A possible solution in the future language revisions could be to introduce
type constructors/destructors: user-defined procedures called upon
derivation and leaving the scope of a type.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Access to function returning class-wide type
  2008-08-21 10:13 Access to function returning class-wide type Paweł 'Nivertius' Płazieński
                   ` (2 preceding siblings ...)
  2008-08-21 12:01 ` Georg Bauhaus
@ 2008-08-21 17:02 ` Adam Beneschan
  2008-08-21 19:22   ` Paweł 'Nivertius' Płazieński
  3 siblings, 1 reply; 15+ messages in thread
From: Adam Beneschan @ 2008-08-21 17:02 UTC (permalink / raw)


On Aug 21, 3:13 am, Paweł 'Nivertius' Płazieński <nivert...@gmail.com>
wrote:
> Hello all.
>
> I'm new here, but I'll try to stick on.
>
> Let me start with a tricky problem:
>
> Consider following code:
>
> ----------------------------------------
>
> package A is
>         type Abstracted is abstract tagged null record;
>         function Proc (N : Natural) return Abstracted is abstract;
>
>         type The_Access_Type is access function (N : Natural) return
> Abstracted'Class;
>
> end A;
>
> -- package A body ommited;
>
> with A;
> package B is
>         type Derived is new A.Abstracted with null record;
>         function Proc (N : Natural) return Derived;
>
>         Failing_Object : A.The_Access_Type := B.Proc'Access;
>         --  will not compile, error: 'expected type The_Access_Type / found type
> access function Proc defined at ...'
>
>         function Proc_Wrapper (N : Natural) return Abstracted'Class;
>
>         Working_Object : A.The_Access_Type := B.Proc_Wrapper'Access;
>         -- compiler doesn't complain
>
> end B;
>
> package B body is
>         function Proc_Wrapper (N : Natural) return Abstracted'Class is
>         begin
>                 return Abstracted'Class'(Proc (N));
>         end Proc;
>
>         -- function Proc body ommited
> end B;
>
> ----------------------------------------
>
> What I need is a access type to 'constructor' of an derivate of abstract
> object.
> As I presented, there is a workaround, but that's not the 'right' way to do
> it. I really want to do it without some tricky wrapping.
> How do I define The_Access_Type to do what I want?

Others have posted discussions of how to accomplish what you want, or
what we think you might want, using a different construct.

I just wanted to point out that, from a low-level standpoint, there's
no way to have an access type that could refer to *both* a function
that returns Abstracted'Class *and* a function that returns the
specific type Derived.  The reason is that an access-to-function is
basically just going to hold the address of the function (and some
other information).  A function that returns T'Class can't work the
same as a function that returns a specific type, because the function
that returns T'Class won't know in advance how big the return object
is going to be, so some dynamic heap (or "secondary stack") allocation
must be involved.  A function that returns Derived, though, knows how
big the return object is, so the result can be pre-allocated.  This
means that both the function and the function's caller have to adopt
different mechanisms for passing the return object between them.  If
you have an access-to-function which could point to either one, the
code that makes a call through this access-to-function pointer isn't
going to know which return object mechanism would be used, so  the
result would be a mess.

If Ada were to provide a mechanism so that B.Proc'Access could be
used, the compiler would have to generate its own wrapper, same as
you're doing.  This isn't necessarily a bad thing; there are already
other cases where Ada compilers have to generate wrappers (at least
ours does).  But I think it's useful to understand the underlying
mechanisms involved, to get a better understanding of why the language
won't let you do certain things.

By the way, if you decide that the other suggestions don't work and
you need to write a wrapper anyway, you shouldn't have to rewrite the
whole wrapper for every type; I think you can use a generic to make
the process of declaring the wrapper a lot simpler.

                             -- Adam




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

* Re: Access to function returning class-wide type
  2008-08-21 17:02 ` Adam Beneschan
@ 2008-08-21 19:22   ` Paweł 'Nivertius' Płazieński
  0 siblings, 0 replies; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 19:22 UTC (permalink / raw)


Adam Beneschan wrote:

> Others have posted discussions of how to accomplish what you want, or
> what we think you might want, using a different construct.

I watched comp.lang.ada for little time, searched through posts which I got
and I belive I didn't see that. I'm sorry if I browsed to short.

> I just wanted to point out that, from a low-level standpoint, there's
> no way to have an access type that could refer to *both* a function
> that returns Abstracted'Class *and* a function that returns the
> specific type Derived.  The reason is that an access-to-function is
> basically just going to hold the address of the function (and some
> other information).  A function that returns T'Class can't work the
> same as a function that returns a specific type, because the function
> that returns T'Class won't know in advance how big the return object
> is going to be, so some dynamic heap (or "secondary stack") allocation
> must be involved.  A function that returns Derived, though, knows how
> big the return object is, so the result can be pre-allocated.  This
> means that both the function and the function's caller have to adopt
> different mechanisms for passing the return object between them.  If
> you have an access-to-function which could point to either one, the
> code that makes a call through this access-to-function pointer isn't
> going to know which return object mechanism would be used, so  the
> result would be a mess.
> 
> If Ada were to provide a mechanism so that B.Proc'Access could be
> used, the compiler would have to generate its own wrapper, same as
> you're doing.  This isn't necessarily a bad thing; there are already
> other cases where Ada compilers have to generate wrappers (at least
> ours does).  But I think it's useful to understand the underlying
> mechanisms involved, to get a better understanding of why the language
> won't let you do certain things.

I think I understand what you want to show me. As I posted in other thread
[see news:g8jf3n$e00$1@registered.motzarella.org ], I've made a test with
type/subtype and it's failing as well. There is a more obvious collision
there, we expect a function which doesn't do dynamic range check on
returned object, and we pass a function which does.

> By the way, if you decide that the other suggestions don't work and
> you need to write a wrapper anyway, you shouldn't have to rewrite the
> whole wrapper for every type; I think you can use a generic to make
> the process of declaring the wrapper a lot simpler.

As I've shown in original post, the wrapper needs to consist only a return
statement from 'main' constructor. I'll try to do it with generic function
as you suggest, but in the worst case the difference will be... well...
small ;-)

-- 
Pawe� P�azie�ski aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 13:50     ` Dmitry A. Kazakov
@ 2008-08-21 19:30       ` Paweł 'Nivertius' Płazieński
  2008-08-21 20:56         ` Dmitry A. Kazakov
  0 siblings, 1 reply; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-21 19:30 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> So you could replace it with a map condition->type tag and then proceed
> with Ada.Tags.Generic_Dispatching_Constructor, because the map
> tag->constructor is for free, here you do not need pointers any more, in
> Ada 2005. The compiler will force to override the "constructor" for each
> concrete derived type.
> -------------
> Having said that, there still is a difficult problem with construction of
> the map. I don't know if it is an issue for you, but it is for the
> persistency layer I designed. The problem is that if the map is
> open-ended, you need some mechanism of registration of each new type in
> the map. This is still unresolved in Ada. The pattern I am using is that
> each package declaring a new type is required to call some class-wide
> procedure registering the type upon package elaboration. In your case it
> is the condition associated with the type tag. That cannot be enforced,
> and it works only at the library level, i.e. for "immortal" types.

I think that the map condition->type tag is in my case same problem as map
condition->constructor pointer. I need the map registration anyway, because
it basically needs to be changed at run-time. Altrough, all the types I
need to register are library-level types, so the registration mechanism is
pretty simple.

> A possible solution in the future language revisions could be to introduce
> type constructors/destructors: user-defined procedures called upon
> derivation and leaving the scope of a type.

I can't wait to see that :-)

-- 
Pawe� P�azie�ski aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-21 19:30       ` Paweł 'Nivertius' Płazieński
@ 2008-08-21 20:56         ` Dmitry A. Kazakov
  2008-08-22  7:34           ` Paweł 'Nivertius' Płazieński
  0 siblings, 1 reply; 15+ messages in thread
From: Dmitry A. Kazakov @ 2008-08-21 20:56 UTC (permalink / raw)


On Thu, 21 Aug 2008 21:30:28 +0200, Pawe� 'Nivertius' P�azie�ski wrote:

> Dmitry A. Kazakov wrote:
> 
>> So you could replace it with a map condition->type tag and then proceed
>> with Ada.Tags.Generic_Dispatching_Constructor, because the map
>> tag->constructor is for free, here you do not need pointers any more, in
>> Ada 2005. The compiler will force to override the "constructor" for each
>> concrete derived type.
>> -------------
>> Having said that, there still is a difficult problem with construction of
>> the map. I don't know if it is an issue for you, but it is for the
>> persistency layer I designed. The problem is that if the map is
>> open-ended, you need some mechanism of registration of each new type in
>> the map. This is still unresolved in Ada. The pattern I am using is that
>> each package declaring a new type is required to call some class-wide
>> procedure registering the type upon package elaboration. In your case it
>> is the condition associated with the type tag. That cannot be enforced,
>> and it works only at the library level, i.e. for "immortal" types.
> 
> I think that the map condition->type tag is in my case same problem as map
> condition->constructor pointer. I need the map registration anyway, because
> it basically needs to be changed at run-time.

Why then N is a parameter? When each type knows its N you don't need to
pass it back.

> Altrough, all the types I
> need to register are library-level types, so the registration mechanism is
> pretty simple.

Then the pattern is (assuming N is unknown in advance):

package A is 
   type Abstracted is abstract tagged null record;
   procedure Register
             (  N : out Natural; -- Given upon registration
                Constructor : not null access
                   function return Abstracted'Class
             );
end A;
   
package B is
   type Derived is new Abstracted with ...;
end B;

package body B is
   My_N : Natural;

   function Create return Abstracted'Class is
   begin
        return Derived'(...); -- Returns derived
   end Create;

begin
   Register (My_N, Create'Access);
end B;

You don't need to declare Create in A at all. Each type will declare it in
order to call to Register anyway.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



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

* Re: Access to function returning class-wide type
  2008-08-21 13:34     ` Dmitry A. Kazakov
@ 2008-08-22  4:53       ` Randy Brukardt
  2008-08-22 23:50         ` Randy Brukardt
  0 siblings, 1 reply; 15+ messages in thread
From: Randy Brukardt @ 2008-08-22  4:53 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> wrote in message 
news:tslrrr8w3j63.zp28ykzgmr23.dlg@40tude.net...
...
> P.S. I don't know reasons why it was decided to use an access type in
> Ada.Tags.Generic_Dispatching_Constructor profile. One could always pass a
> pointer there if a side effect on the parameters were desired. But that is
> another issue, and in any case Proc is thought as an implementation 
> detail,
> so its exact profile should not really matter.

I originally came up with this proposal (based on random thoughts tossed out 
by Steve Baird and Tucker Taft). We'd been trying to find solutions for 
literally years; I was amazed that this one didn't fall into a heap of slag 
as the others had.

Anyway, the access parameter exists so that an instance of this routine 
matches the profile of S'Class'Input. After all, the purpose of this routine 
is to eliminate the Ada 95 compiler magic involved with S'Class'Input and 
make it user-programmable. The thought is that a user-defined version of 
S'Class'Input would be directly specified as an instance of 
Generic_Dispatching_Constructor.

In hindsight, I'm not certain that is a good idea, because it mucks up the 
spec for no particularly good reason. But that's the way it is now.

                                                   Randy.






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

* Re: Access to function returning class-wide type
  2008-08-21 20:56         ` Dmitry A. Kazakov
@ 2008-08-22  7:34           ` Paweł 'Nivertius' Płazieński
  0 siblings, 0 replies; 15+ messages in thread
From: Paweł 'Nivertius' Płazieński @ 2008-08-22  7:34 UTC (permalink / raw)


Dmitry A. Kazakov wrote:

> Why then N is a parameter? When each type knows its N you don't need to
> pass it back.

To be perfectly honest, the parameter in my specific case is not a Natural
[it was just an example], but complex type. Type of the produced object is
determined on one part and the distinct type is built on the whole object.
Sorry for misleading you, but for natural it also can be the case:
When the condition is N in 1 .. 12, type should be Derived_1 build on that
N.

-- 
Pawe� P�azie�ski aka Nivertius
"In the end, there will be Ada, XML and gzip"



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

* Re: Access to function returning class-wide type
  2008-08-22  4:53       ` Randy Brukardt
@ 2008-08-22 23:50         ` Randy Brukardt
  0 siblings, 0 replies; 15+ messages in thread
From: Randy Brukardt @ 2008-08-22 23:50 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> wrote in message 
news:g8lgof$54c$1@jacob-sparre.dk...
...
> Anyway, the access parameter exists so that an instance of this routine 
> matches the profile of S'Class'Input. After all, the purpose of this 
> routine is to eliminate the Ada 95 compiler magic involved with 
> S'Class'Input and make it user-programmable. The thought is that a 
> user-defined version of S'Class'Input would be directly specified as an 
> instance of Generic_Dispatching_Constructor.

I realized just now that I screwed up this answer, it doesn't make much 
sense as I wrote it above. The correct reason was so that S'Input could be 
used as the constructor routine to an instance of 
Generic_Dispatching_Constructor, and then that instance could be used as 
part of a routine implementing a user-defined S'Class'Input. Sorry about any 
confusion.

                                          Randy.





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

end of thread, other threads:[~2008-08-22 23:50 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-08-21 10:13 Access to function returning class-wide type Paweł 'Nivertius' Płazieński
2008-08-21 10:33 ` Paweł 'Nivertius' Płazieński
2008-08-21 11:02 ` Dmitry A. Kazakov
2008-08-21 11:56   ` Paweł 'Nivertius' Płazieński
2008-08-21 13:34     ` Dmitry A. Kazakov
2008-08-22  4:53       ` Randy Brukardt
2008-08-22 23:50         ` Randy Brukardt
2008-08-21 12:01 ` Georg Bauhaus
2008-08-21 13:01   ` Paweł 'Nivertius' Płazieński
2008-08-21 13:50     ` Dmitry A. Kazakov
2008-08-21 19:30       ` Paweł 'Nivertius' Płazieński
2008-08-21 20:56         ` Dmitry A. Kazakov
2008-08-22  7:34           ` Paweł 'Nivertius' Płazieński
2008-08-21 17:02 ` Adam Beneschan
2008-08-21 19:22   ` Paweł 'Nivertius' Płazieński

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