FIAT
FIAT copied to clipboard
why transfer-trick instead of class(*)?
Hi @cmacmackin ,
I have restarted to study FIAT with hope to contribute to it. I am now going to develop an hash-table with the hope to merge into FIAT.
I am almost sure I have asked this already, but I do not remember your answer... sorry.
For your abstract container you encode data by transfer built-in, e.g.
type, public, abstract :: container
private
integer(i1), dimension(:), allocatable :: storage !! Variable in which to place data contents
logical :: filled = .false. !! `.true.` if container is set, `.false.` otherwise
contains
private
procedure(guard), deferred :: typeguard
...
end type container
I also used transfer-trick for generic list before class(*) becomes available in my main-stream compiler at that time. Now, I am wondering which are the advantages to prefer transfer-trick over the unlimited polymorphic data. For example I like to have the contained data defined as a pointer in order to avoid copy-in-copy-out every-time I manage the data (that in my application case could be large, order of 100MB). Moreover, you already use the select type cluttering-syntax for the typeguard method, thus the main cons of class(*) is already accomplished.
Currently, I am playing with something like
type, public, abstract :: container
private
class(*), pointer :: storage !! Variable in which to place data contents
logical :: filled = .false. !! `.true.` if container is set, `.false.` otherwise
contains
private
procedure(guard), deferred :: typeguard
procedure(associate_to_contents_interface), deferred :: associate_to_contents
...
end type container
where the associate_to_contents is similar to your typeguard, but performs only a pointer association.
I would like to know your opinions, in particular what you think are the main pros of transfer-trick over class(*).
Cheers.
I used the transfer approach because I find that use of class(*) can be buggy, although no doubt this has improved in more recent versions of GCC. In particular, I've sometimes had issues where massive amounts of memory get allocated for no apparent reason.
Your comment about pointers is valid. I had originally intended for containers to hold only non-pointer values because I try to avoid pointers when I use Fortran (that way I don't have to worry about memory management). However, I have been thinking for some time that it would be useful to define a version of the container class which can use pointers. Likely both this and my existing implementation would then inherit from an abstract derived type.
@cmacmackin Chris, thank you very much for your explanation. At that time I also relied on transfer because class() was not *mature.
If you agree, I am going on with class() pointer, then when I'll feel this could be considered *stable I'll try to merge alongside the stantard allocatable storage in a complementary way.
Cheers.
I certainly don't mind. Could you please take the approach of using an abstract parent type for both the pointer and non-pointer containers and maintain, as far as is practical, a common interface for the two?
On 02/10/16 13:23, Stefano Zaghi wrote:
@cmacmackin https://github.com/cmacmackin Chris, thank you very much for your explanation. At that time I also relied on transfer because class(/) was not *mature/.
If you agree, I am going on with class(/) pointer, then when I'll feel this could be considered *stable/ I'll try to merge alongside the /stantard/ allocatable storage in a complementary way.
Cheers.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/Fortran-FOSS-Programmers/FIAT/issues/5#issuecomment-250968730, or mute the thread https://github.com/notifications/unsubscribe-auth/AHxJPYo5jukBk2mwEjwAsrPV01GjqcC1ks5qv6JYgaJpZM4KLt3n.
Chris MacMackin cmacmackin.github.io http://cmacmackin.github.io
Yes, @cmacmackin's suggestion is quite prudent, in my opinion. That way you can always use an (abstract) factory pattern to construct the desired instantiation of the object (transfer based or unlimited polymorphic) but then return a reference to an object of the parent abstract class. This way the client code is only exposed to the interface and not the implementation.
@cmacmackin @zbeekman this is exactly what I planned to do.