Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

why transfer-trick instead of class(*)? #5

Open
szaghi opened this issue Oct 1, 2016 · 5 comments
Open

why transfer-trick instead of class(*)? #5

szaghi opened this issue Oct 1, 2016 · 5 comments

Comments

@szaghi
Copy link
Member

szaghi commented Oct 1, 2016

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.

@cmacmackin
Copy link
Collaborator

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.

@szaghi
Copy link
Member Author

szaghi commented Oct 2, 2016

@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.

@cmacmackin
Copy link
Collaborator

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
#5 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHxJPYo5jukBk2mwEjwAsrPV01GjqcC1ks5qv6JYgaJpZM4KLt3n.

Chris MacMackin
cmacmackin.github.io http://cmacmackin.github.io

@zbeekman
Copy link
Member

zbeekman commented Oct 2, 2016

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.

@szaghi
Copy link
Member Author

szaghi commented Oct 2, 2016

@cmacmackin @zbeekman this is exactly what I planned to do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants