- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran Gurus: say I have two unlimited polymorphic variables (CLASS(*)), and I want to check if they are equal. Does anyone know if there is a better way than having to write nested SELECT TYPE statements for all possible variable types? Basic example below. Assuming I only cared about built-in variables types (integers, etc.) I'd have to write cases for INT8, INT16, INT32, INT64, REAL32, REAL64, REAL128, and CHARACTERS kinds. This seems unsatisfactory to me, but I can't think of any other way to do it.
function equal(k1,k2) implicit none class(*),intent(in) :: k1 class(*),intent(in) :: k2 logical :: equal equal = .false. if (same_type_as(k1,k2)) then select type (k1) type is (integer) select type (k2) type is (integer) equal = k1 == k2 end select type is (character(len=*)) select type (k2) type is (character(len=*)) equal = k1 == k2 end select !type is (...), etc. end select end if end function equal
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Mmm I would have thought that since you have already determined that k1 and k2 are the same type that you can just simply do:
equal = k1 == k2
But it is early and I haven't had my coffee yet so I may be wrong :-(
Les
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
How do you establish that the two types are the same without using select type?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Get the number of bytes and compare each byte.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry but I don't really understand that, could you post a code snippet by way of explanation please. Unlike the OP I already have this problem with user-defined types so a way of removing hundreds of lines of what seems like unnecessary code would be very welcome. Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There is no other way.
(You can "cast" with unlimited polymorphic pointers to SEQUENCE or BIND(C) types without SELECT TYPE, but that is not the general case.)
I do not recommend comparing bytes, because polymorphic objects are internally managed via a descriptor of sorts that is likely to fail anyway, plus the same byte sequence can represent different values.
It would be worth testing the decision to use unlimited polymorphic objects in the first place. It depends a great deal on what you are Trying to do, but if all the objects that you are trying to compare are an extension of a common base type, you can potentially eliminate one of the SELECT TYPE constructs, replacing it with a type bound procedure for each subject type that implements the equality comparison operator.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH wrote:
..
It would be worth testing the decision to use unlimited polymorphic objects in the first place. It depends a great deal on what you are Trying to do, but ..
Yes, this suggestion makes most sense. OP may want to look back and consider whether the use of unlimited polymorphism is really necessary for the given situation - a code review perhaps using techniques in OO design and analysis might reveal better ways to go about achieving the needs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My example is somewhat academic. I was experimenting with creating a dictionary class, where the key could be any numeric or string type (similar to the way Python works). It seemed reasonable to store this variable as an unlimited polymorphic. But in the instance when I need to check if two keys are equal, I encounter this issue (SELECT TYPE works fine, but I was just wondering if there was another way).
In this case, since k1 and k2 are only allowed to be numbers or strings, I wonder if comparing the bytes might be OK (assuming I keep the SAME_TYPE_AS check to ensure that they are really the same kind of variable). Perhaps using some TRANSFER magic and maybe also BTEST? I'll give that a try.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jacob Williams wrote:
My example is somewhat academic. I was experimenting with creating a dictionary class, where the key could be any numeric or string type (similar to the way Python works). It seemed reasonable to store this variable as an unlimited polymorphic. But in the instance when I need to check if two keys are equal, I encounter this issue (SELECT TYPE works fine, but I was just wondering if there was another way).
In this case, since k1 and k2 are only allowed to be numbers or strings, I wonder if comparing the bytes might be OK (assuming I keep the SAME_TYPE_AS check to ensure that they are really the same kind of variable). Perhaps using some TRANSFER magic and maybe also BTEST? I'll give that a try.
Well, if your interest is in something like a dictionary class, then you're on the right track by thinking of TRANSFER intrinsic - I do use something along the same lines in some of my classes. See this thread and the code snippet in Message #22 for an example that may be of interest for what you are trying to do:
https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/541989
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Luigi R. wrote:
Get the number of bytes and compare each byte.
A user defined type may contain POINTERs and/or ALLOCATABLEs therefore byte compare is not suitable excepting for identity and/or pointer to identity. Depending on your needs for operator==, you will generally want to dereference the pointer and/or array descriptor.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
How about something like this:
function equal(k1,k2) implicit none class(*),intent(in) :: k1 class(*),intent(in) :: k2 logical :: equal equal = k1%equal(k2) end function equal
Each class/type will have the responsibility of having a contains function for equality of same type.
You can make a generic interface for equal, test the equality of native types:
interface equal function equal_class(k1,k2) implicit none class(*),intent(in) :: k1 class(*),intent(in) :: k2 logical :: equal end function equal_class function equal_integer(k1,k2) implicit none integer,intent(in) :: k1 integer,intent(in) :: k2 logical :: equal end function equal_integer ... end interface equal contains function equal_class(k1,k2) implicit none class(*),intent(in) :: k1 class(*),intent(in) :: k2 logical :: equal equal = k1%equal(k2) end function equal function equal_integer(k1,k2) implicit none integer,intent(in) :: k1 integer,intent(in) :: k2 logical :: equal equal = (k1 == k2) end function equal_integer
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jimdempseyatthecove wrote:
.. You can make a generic interface for equal, test the equality of native types: ..
Jim Dempsey
You cannot make a generic interface of class(*) dummy arguments along with native types - it creates ambiguous interfaces that cannot be resolved.
And the situation is no different than in the original post: OP will need to provide interfaces for each type to be supported.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
>>You cannot make a generic interface of class(*) dummy arguments along with native types - it creates ambiguous interfaces that cannot be resolved.
It is not necessarily ambiguous. If the native types (without promotion/demotion/conversion) are resolvable with the generic interface, then the class(*) dummy arguments calling formats should not be considered. This said, the Fortran standards committee probably couldn't agree on how to do this. C++ managed to do this a long time ago.
Maybe Steve will comment on this.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Is a particular dictionary limited to only entries of a particular type (i.e. dictionary A has only CHARACTER, dictionary B has only INTEGER), or can they be mixed within the one dictionary?
(Further to FortranFan's comments, the function reference `k1%equal(k2)` where k1 is unlimited polymorphic will not compile - when the declared type is unlimited polymorphic, no components or bindings are available. Also, generic resolution only considers declared type, but it is the dynamic type that you want to dispatch on.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IanH,
Thanks for pointing out that an arbitrary unlimited polymorphic is not required to have the same set of what amounts to member functions. You may be able to have a nested class, where the base class does, but then your outer program layer is then using these base classes. Also this would not reduce your coding effort, as my suggestion sought to achieve.
Jim Dempsey

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page