From: Markus Schoepflin on
Markus Schoepflin wrote:
> Dmitry A. Kazakov wrote:
>
> [...]
>
> Thanks for you swift and helpful reply.
>
>> If P is to be defined in terms of any type from the class FOO, then P has
>> to be declared differently (class-wide):
>
> So If I understand this correctly, if I want dispatching to happen on a
> given type, I always need to use the class type?
>

And one more question, can I have a dispatching procedure that doesn't
explicitly use the type it dispatches on? In C++, that would read:

class foo
{
virtual void f() = 0;
};

class bar
{
void f() {
// Do something just depending on class type bar,
// not on an object of the class, so the 'this' pointer
// actually is never used.
}
};

Markus
From: Niklas Holsti on
Markus Schoepflin wrote:
> Dmitry A. Kazakov wrote:
>
> [...]
>
> Thanks for you swift and helpful reply.
>
>> If P is to be defined in terms of any type from the class FOO, then P has
>> to be declared differently (class-wide):
>
> So If I understand this correctly, if I want dispatching to happen on a
> given type, I always need to use the class type?

Yes. You can do that either by Dmitry's method, declaring the parameter
as FOO'Class, or by converting a FOO parameter to FOO'Class for the
call. But note that if an operation has no parameters (and no return
value) of type FOO (or access FOO), only of FOO'Class, it is not a
primitive operation of FOO and cannot be overridden in derived types.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
From: Dmitry A. Kazakov on
On Fri, 20 Nov 2009 14:43:45 +0100, Markus Schoepflin wrote:

> So If I understand this correctly, if I want dispatching to happen on a
> given type, I always need to use the class type?

Exactly.

This helps both the compiler to make the program much more efficient by
eliminating unnecessary dispatch and you indicating the design problems
like this and making it safer in the opposite cases:

Consider the case where one non-abstract operation calls another:

type FOO is abstract tagged null record;
procedure P (THIS : in out FOO);
procedure A (THIS : in out FOO);

....
procedure P (THIS : in FOO) is
begin
...
A (THIS);
-- This is a part of the implementation of P for the type FOO
...
end P;

Here the call to A does not dispatch. In other language like C++ it would.

Now consider a type derived from FOO, that overrides A, but inherits P.
That could break the implementation of P in C++, but not in Ada, where P
will behave exactly as it did before.

When you design P you should decide whether it is a class-wide subprogram
or not. That role of P will define the behavior of calls to A from its
body. Sometimes the compiler can detect that the declared role of P does
not match its implementation, as it was in your case.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Niklas Holsti on
> On Fri, 20 Nov 2009, Markus Schoepflin wrote:
>
>
>> ---%<---
>> package FOOS is
>>
>> type FOO is abstract tagged null record;
>>
>> procedure P (THIS : in FOO);
>
> -------> replace by
> procedure P (THIS : in FOO'Class);
>
>> procedure A (THIS : in FOO) is abstract;
>>
>> end FOOS;
>>
>> package body FOOS is
>>
>> procedure P (THIS : in FOO)
>
> -------> replace by
> procedure P (THIS : in FOO'Class);
>
>> is
>> begin
>> A (THIS);
>> end;
>>
>> end FOOS;
>> --->%---
>>
>> When trying to compile this, I get:
>>
>> foos.adb:6:07: call to abstract function must be dispatching
>> gnatmake: "foos.adb" compilation error
>>
>> What is the compiler trying to tell me here? And how do I go
>> about calling abstract procedures?
>>
>> TIA,
>> Markus

stefan-lucks(a)see-the.signature wrote:
> If Foo is a tagged type, then
> "procedure A(This: [in] [out] Foo)"
>
> expects *exactly* the same type as the actual parameter. If you want
> "either type Foo or any of its object-oriented children" you write
>
> "procedure B(This: [in] [out] Foo'Class)".
>
> In your case, Foo is an abstract tagged type. As much as I seem to
> understand Ada, there is no way to actually call procedure A -- because
> you can't have any actuals of an abstract type. (Hey you guys out there,
> am I wrong?)

There is no way to call A on an object of (apparent) type FOO because A
is declared as abstract for FOO. The compiler very correctly says that
such a call is impossible.

But you can call the overriding (concrete) implementation of A for the
actual type of THIS (some non-abstract type derived from FOO) by
converting to class-wide to force dispatching:

A (FOO'Class (THIS));

> If I am right, it is very regrettable that the compiler doesn't issue a
> warning when compiling "procedure A(This: [in] [out] Foo)" for an abstract
> type Foo ... perhaps better, a revised Ada should prohibit that.

There is no reason for such a warning because defining A in this way is
legal and useful, as long as you convert the parameter to FOO'Class when
you call it. You can consider the name A (of the abstract operation) a
kind of place-holder for all the concrete implementations of A for
derived types.

But Dmitry probably thinks that there should be warning of the form "Bad
design! Naughty!" :-)

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .

From: Niklas Holsti on
Markus Schoepflin wrote:
> Markus Schoepflin wrote:
>> Dmitry A. Kazakov wrote:
>>
>> [...]
>>
>> Thanks for you swift and helpful reply.
>>
>>> If P is to be defined in terms of any type from the class FOO, then P
>>> has
>>> to be declared differently (class-wide):
>>
>> So If I understand this correctly, if I want dispatching to happen on
>> a given type, I always need to use the class type?
>>
>
> And one more question, can I have a dispatching procedure that doesn't
> explicitly use the type it dispatches on?

No, as there is no implicit "this" parameter in Ada (and no syntactic
brackets to group all the operations of a type). To make an operation
overridable (a "primitive operation" in Ada terms) you have to include
one or more parameters of the type (or of "access" to the type) or it
must return a value of the type (or "access" to the type). And moreover
the operation must be declared in the same package declaration as the type.

--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .