From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=unavailable autolearn_force=no version=3.4.4 Path: eternal-september.org!reader01.eternal-september.org!reader02.eternal-september.org!news.eternal-september.org!news.eternal-september.org!feeder.eternal-september.org!border1.nntp.ams1.giganews.com!nntp.giganews.com!peer01.ams1!peer.ams1.xlned.com!news.xlned.com!peer01.am4!peer.am4.highwinds-media.com!peer04.fr7!futter-mich.highwinds-media.com!news.highwinds-media.com!fx39.am4.POSTED!not-for-mail Subject: Re: Smart Pointers and Tagged Type Hierarchies Newsgroups: comp.lang.ada References: <2017072417413775878-contact@flyx.org> From: Chris Moore User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 In-Reply-To: <2017072417413775878-contact@flyx.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: 7bit Message-ID: X-Complaints-To: http://netreport.virginmedia.com NNTP-Posting-Date: Mon, 24 Jul 2017 21:24:57 UTC Organization: virginmedia.com Date: Mon, 24 Jul 2017 22:24:58 +0100 X-Received-Body-CRC: 2311975209 X-Received-Bytes: 3408 X-Original-Bytes: 3232 Xref: news.eternal-september.org comp.lang.ada:47509 Date: 2017-07-24T22:24:58+01:00 List-Id: On 24/07/2017 16:41, Felix Krause wrote: > With Ada's controlled types, it is possible to implement smart pointers > which manage heap objects with reference-counting. There is more than > one tutorial showing how that works. > > A problem I encounter is how this can be used with type hierarchies i.e. > I have a smart pointer managing a tagged type, and I want to be able to > derive from that tagged type and still be able to use my smart pointer > with that new type. Let me give an example: Assume I want to implement > an abstract type Stream that represents a stream of events (has nothing > to do with Ada.Streams). I will use a slightly modified Rosen '95 name > scheme here for clarity: Reference is the smart pointer, Instance is the > actual object. Let this be the base type: > > > Some observations: > > * Unless all implementations are child classes of Stream, it is > necessary to make the Instance type public. Obv. > * A derived type, if it wants to provide additional operations (like > Current_Position), must not only derive from Instance, but also from > Reference, to be able to provide an type-safe interface to those > operations. Why? All ops on Instance-derived types (including constructing subprograms) should be in terms of that type. References are for access only (ho ho). > * As types derived from Stream possibly need to derive Stream.Reference, > a consumer of a Stream object needs to take a Stream.Reference'Class as > input. This type cannot be used for a record field, so I need to > allocate it in heap memory and store a pointer if I want to memorize a > Stream.Reference value anywhere. No. This way lies madness. A parallel hierarchy of References gains you very little and takes a lot of maintenance. > * The implementation of Current_Position is cumbersome as I need the > Implementation_Access function and convert the result to > File_Stream.Instance, which creates a needless downcast check. The downcast has to go *somewhere*. I had to do this kind of thing a great deal in the Ada version of the mal lisp interpreter. See for example: https://github.com/zmower/mal/blob/master/ada/smart_pointers.ads https://github.com/zmower/mal/blob/master/ada/types.ads But my advice is to avoid tagged types if you can. They only make sense if your problem is wildly dynamic or you want to be lazy when thinking about memory allocation. mal qualified on both counts.