comp.lang.ada
 help / color / mirror / Atom feed
* Confused about class-wide types
@ 2016-03-20 11:15 Mart van de Wege
  2016-03-20 12:29 ` Dmitry A. Kazakov
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Mart van de Wege @ 2016-03-20 11:15 UTC (permalink / raw)


Hi,

I'm finding myself a little confused about the interaction between
class-wide types.

Here's some example code:

Spec:

with Ada.Containers.Vectors;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
package Types_Test is
   type Event is abstract tagged null record;
   type Event_Ptr is access Event'Class;
   type Message_Event is new Event with private;
   type Message_Event_Ptr is access Message_Event'Class;
   procedure Message (M : in out Message_Event_Ptr;
		      Mess : in String);
   package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
						 Element_Type => Event_Ptr);
private
   type Message_Event is new Event with record
      Message : Unbounded_String;
   end record;
end Types_Test;

Test program:

with Types_Test; use Types_Test;
procedure Test_Type
is
   M : Message_Event_Ptr;
   Log : Events.Vector;
begin
   M := new Message_Event;
   Message(M,"Test Message");
   Log.Append(M);
end Test_Type;

The idea is that Events.Vector should be able to hold different types of
Events. Yet if I compile it this way, GNAT bombs out with:

test_type.adb:9:15: expected type "Event_Ptr" defined at types_test.ads:5
test_type.adb:9:15: found type "Message_Event_Ptr" defined at types_test.ads:7

Obviously, I'm doing something wrong; I'm probably misunderstanding
something, but what?

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

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

* Re: Confused about class-wide types
  2016-03-20 11:15 Confused about class-wide types Mart van de Wege
@ 2016-03-20 12:29 ` Dmitry A. Kazakov
  2016-03-20 13:58   ` Mart van de Wege
  2016-03-20 12:46 ` Simon Wright
  2016-03-20 13:18 ` Shark8
  2 siblings, 1 reply; 9+ messages in thread
From: Dmitry A. Kazakov @ 2016-03-20 12:29 UTC (permalink / raw)


On 2016-03-20 12:15, Mart van de Wege wrote:

> I'm finding myself a little confused about the interaction between
> class-wide types.
>
> Here's some example code:
>
> Spec:
>
> with Ada.Containers.Vectors;
> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
> package Types_Test is
>     type Event is abstract tagged null record;
>     type Event_Ptr is access Event'Class;
>     type Message_Event is new Event with private;
>     type Message_Event_Ptr is access Message_Event'Class;
>     procedure Message (M : in out Message_Event_Ptr;
> 		      Mess : in String);

    function Message (Mess : in String) return Event_Ptr;

>     package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
> 						 Element_Type => Event_Ptr);
> private
>     type Message_Event is new Event with record
>        Message : Unbounded_String;
>     end record;
> end Types_Test;
>
> Test program:
>
> with Types_Test; use Types_Test;
> procedure Test_Type
> is
>     M : Message_Event_Ptr;
>     Log : Events.Vector;
> begin
>     M := new Message_Event;
>     Message(M,"Test Message");
>     Log.Append(M);
> end Test_Type;
 >
> The idea is that Events.Vector should be able to hold different types of
> Events. Yet if I compile it this way, GNAT bombs out with:

    Log.Append (Message ("Test Message"));

> test_type.adb:9:15: expected type "Event_Ptr" defined at types_test.ads:5
> test_type.adb:9:15: found type "Message_Event_Ptr" defined at types_test.ads:7
>
> Obviously, I'm doing something wrong; I'm probably misunderstanding
> something, but what?

Ada has named types equivalence. Event_Ptr and Message_Event_Ptr are two 
independent types regardless what they point to. If you declared

    type Message_Event_Ptr is access Event'Class;

It would not work. Event if you did

    type Message_Event_Ptr is new Event_Ptr;

It still would not.

All this is unrelated to class-wide vs specific types.

BTW, it is a bad idea to use pointers, as bad as using vectors for a 
FIFO or Unbounded_String to keep constant strings. To dynamically 
allocate Unbounded_String which contents is again dynamically allocated 
is quite bizarre. Pointers could be used with queues when messages are 
pre-allocated elsewhere, in order to avoid copying overhead.

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


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

* Re: Confused about class-wide types
  2016-03-20 11:15 Confused about class-wide types Mart van de Wege
  2016-03-20 12:29 ` Dmitry A. Kazakov
@ 2016-03-20 12:46 ` Simon Wright
  2016-03-20 14:01   ` Mart van de Wege
  2016-03-20 13:18 ` Shark8
  2 siblings, 1 reply; 9+ messages in thread
From: Simon Wright @ 2016-03-20 12:46 UTC (permalink / raw)


Mart van de Wege <mvdwege@gmail.com> writes:

> with Ada.Containers.Vectors;
> with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
> package Types_Test is
>    type Event is abstract tagged null record;
>    type Event_Ptr is access Event'Class;
>    type Message_Event is new Event with private;
>    type Message_Event_Ptr is access Message_Event'Class;

You don't need this; Event_Ptr covers Message_Event'Class.

>    procedure Message (M : in out Message_Event_Ptr;
> 		      Mess : in String);

M should be of type Message_Event.

> Test program:
>
> with Types_Test; use Types_Test;
> procedure Test_Type
> is
>    M : Message_Event_Ptr;

This should be of type Event_Ptr.

>    Log : Events.Vector;
> begin
>    M := new Message_Event;
>    Message(M,"Test Message");

Now it gets tricky.

   Message(Message_Event(M.all),"Test Message");

works, because M.All is of type Event'Class and we can do a view
conversion to Message_Event (that's what it was created as in the first
place; we'd get CE if it wasn't).

I think this is difficult because you've introduced operations for the
child (Message_Event) of which the parent (Event) has no analogue at
all. What is the common operation that all Events must support?
Maybe something like

   procedure Handle (E : Event) is abstract;

Your procedure Message is a factory, I think; it might be better as

   function Message (Mess : in String) return Message_Event;

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

* Re: Confused about class-wide types
  2016-03-20 11:15 Confused about class-wide types Mart van de Wege
  2016-03-20 12:29 ` Dmitry A. Kazakov
  2016-03-20 12:46 ` Simon Wright
@ 2016-03-20 13:18 ` Shark8
  2016-03-20 13:56   ` Mart van de Wege
  2016-03-21 21:54   ` Randy Brukardt
  2 siblings, 2 replies; 9+ messages in thread
From: Shark8 @ 2016-03-20 13:18 UTC (permalink / raw)


On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
> 						 Element_Type => Event_Ptr);


If you are using Ada 2012, then you can change "Events" to Ada.Containers.Indefinite_Vectors with an Element_Type of Event'Class... which should, in turn, eliminate the need for any pointer-types in the test. (It also has the advantage of not needing to check the vector for Null.)


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

* Re: Confused about class-wide types
  2016-03-20 13:18 ` Shark8
@ 2016-03-20 13:56   ` Mart van de Wege
  2016-03-21 21:54   ` Randy Brukardt
  1 sibling, 0 replies; 9+ messages in thread
From: Mart van de Wege @ 2016-03-20 13:56 UTC (permalink / raw)


Shark8 <onewingedshark@gmail.com> writes:

> On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> 						 Element_Type => Event_Ptr);
>
>
> If you are using Ada 2012, then you can change "Events" to
> Ada.Containers.Indefinite_Vectors with an Element_Type of
> Event'Class... which should, in turn, eliminate the need for any
> pointer-types in the test. (It also has the advantage of not needing
> to check the vector for Null.)

So *that* is what Indefinite_Vectors is for. That would solve my issues,
yes.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Confused about class-wide types
  2016-03-20 12:29 ` Dmitry A. Kazakov
@ 2016-03-20 13:58   ` Mart van de Wege
  2016-03-20 14:26     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 9+ messages in thread
From: Mart van de Wege @ 2016-03-20 13:58 UTC (permalink / raw)


"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

>
> Ada has named types equivalence. Event_Ptr and Message_Event_Ptr are
> two independent types regardless what they point to. If you declared
>
Yes, that's what threw me off.

>    type Message_Event_Ptr is access Event'Class;
>
> It would not work. Event if you did
>
>    type Message_Event_Ptr is new Event_Ptr;
>
> It still would not.
>
> All this is unrelated to class-wide vs specific types.
>
> BTW, it is a bad idea to use pointers, as bad as using vectors for a
> FIFO or Unbounded_String to keep constant strings. To dynamically
> allocate Unbounded_String which contents is again dynamically
> allocated is quite bizarre. Pointers could be used with queues when
> messages are pre-allocated elsewhere, in order to avoid copying
> overhead.

Yeah, but when I want to have a number of different Event types with
some common operations that I want to store in a Vector, I either need
pointers, or, as Shark8 points out, an Indefinite_Vector, which I
overlooked.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.


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

* Re: Confused about class-wide types
  2016-03-20 12:46 ` Simon Wright
@ 2016-03-20 14:01   ` Mart van de Wege
  0 siblings, 0 replies; 9+ messages in thread
From: Mart van de Wege @ 2016-03-20 14:01 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> I think this is difficult because you've introduced operations for the
> child (Message_Event) of which the parent (Event) has no analogue at
> all. What is the common operation that all Events must support?
> Maybe something like
>
>    procedure Handle (E : Event) is abstract;
>
> Your procedure Message is a factory, I think; it might be better as
>
>    function Message (Mess : in String) return Message_Event;
>

I was over-designing a bit. At current I only need two classes: an event
with a unstructured String as a Message, and a child event with a bit
more metadata in the record, so I thought I'd start out with an abstract
Event class in my Vector definition, and build the generic operations
first.

Shark8 pointed out the right solution: use an Indefinite_Vector, but
your and Dimitri's posts help a lot with understanding where I went
wrong, thanks.

Mart

-- 
"We will need a longer wall when the revolution comes."
    --- AJS, quoting an uncertain source.

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

* Re: Confused about class-wide types
  2016-03-20 13:58   ` Mart van de Wege
@ 2016-03-20 14:26     ` Dmitry A. Kazakov
  0 siblings, 0 replies; 9+ messages in thread
From: Dmitry A. Kazakov @ 2016-03-20 14:26 UTC (permalink / raw)


On 2016-03-20 14:58, Mart van de Wege wrote:
> "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> writes:

>> BTW, it is a bad idea to use pointers, as bad as using vectors for a
>> FIFO or Unbounded_String to keep constant strings. To dynamically
>> allocate Unbounded_String which contents is again dynamically
>> allocated is quite bizarre. Pointers could be used with queues when
>> messages are pre-allocated elsewhere, in order to avoid copying
>> overhead.
>
> Yeah, but when I want to have a number of different Event types with
> some common operations that I want to store in a Vector,

Variant record is also an option, but not for strings.

> I either need
> pointers, or, as Shark8 points out, an Indefinite_Vector, which I
> overlooked.

A vector is still not a ring buffer / FIFO.

If messages are large you might use handles/pointers to the 
reference-counted object. The FIFO holds handles instead of objects. 
That prevents multiple copying on enqueue/dequeue. Upon enqueue you 
increase the count, upon dequeue you decrease it.

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

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

* Re: Confused about class-wide types
  2016-03-20 13:18 ` Shark8
  2016-03-20 13:56   ` Mart van de Wege
@ 2016-03-21 21:54   ` Randy Brukardt
  1 sibling, 0 replies; 9+ messages in thread
From: Randy Brukardt @ 2016-03-21 21:54 UTC (permalink / raw)


"Shark8" <onewingedshark@gmail.com> wrote in message 
news:c5f5d5ac-89c4-4b60-9388-f461ed69eb0e@googlegroups.com...
>On Sunday, March 20, 2016 at 5:16:24 AM UTC-6, Mart van de Wege wrote:
>>    package Events is new Ada.Containers.Vectors ( Index_Type => Natural,
>> Element_Type => Event_Ptr);
>
>If you are using Ada 2012, then you can change "Events" to 
>Ada.Containers.Indefinite_Vectors ...

Indefinite_Vectors was actually introduced with the original containers 
library in Ada 2005; you don't need Ada 2012 to use it. (Since there are a 
number of non-GNAT compilers that claim to support Ada 2005, using it 
doesn't lock you in quite as much.)

                                                 Randy.



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

end of thread, other threads:[~2016-03-21 21:54 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-03-20 11:15 Confused about class-wide types Mart van de Wege
2016-03-20 12:29 ` Dmitry A. Kazakov
2016-03-20 13:58   ` Mart van de Wege
2016-03-20 14:26     ` Dmitry A. Kazakov
2016-03-20 12:46 ` Simon Wright
2016-03-20 14:01   ` Mart van de Wege
2016-03-20 13:18 ` Shark8
2016-03-20 13:56   ` Mart van de Wege
2016-03-21 21:54   ` Randy Brukardt

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