- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I have a problem I would like to solve but somehow I struggle.
I have different types defined:
! Type KUGS ([KUG]elcheibe) TYPE, PUBLIC :: typeKUGS CHARACTER(4) :: cIdent = 'KUGS' CHARACTER(4) :: cANam = '' CHARACTER(4) :: cMant = '' CHARACTER(4) :: cMat = '' CHARACTER(4) :: cSpaw = '' TYPE(typeKOOS) :: KOOS_P1, KOOS_P2 REAL(8) :: rR1 = -1._dp, rR2 = -1._dp REAL(8) :: rS1 = -1._dp, rS2 = -1._dp REAL(8) :: rRKug CONTAINS PROCEDURE, PUBLIC::setKUGS => setKUGS_sub END TYPE typeKUGS ! Type TORS ([TOR]uscheibe) TYPE, PUBLIC :: typeTORS CHARACTER(4) :: cIdent = 'TORS' CHARACTER(4) :: cANam = '' CHARACTER(4) :: cMant = '' CHARACTER(4) :: cMat = '' CHARACTER(4) :: cSpaw = '' TYPE(typeKOOS) :: KOOS_P1, KOOS_P2 REAL(8) :: rR1 = -1._dp, rR2 = -1._dp REAL(8) :: rS1 = -1._dp, rS2 = -1._dp REAL(8) :: rRtor CONTAINS PROCEDURE, PUBLIC::setTORS => setTORS_sub END TYPE typeTORS
Now I want to define the type typeVAM1 which should have a pointer pointing to a typeKUGS, typeTORS or some other type, but from what I know a pointer always have to be of the same variable type as the target
! Type VAM1 TYPE, PUBLIC :: typeVAM1 CHARACTER(4) :: cIdent = 'VAM1' CHARACTER(4) :: cVNam = '' CHARACTER(1) :: cVTyp = '' CHARACTER(1) :: cMIA = '' CHARACTER(4) :: cVA = '' CHARACTER(4) :: cPA = '' CHARACTER(4) :: cMV = '' CHARACTER(4) :: cVTNa = '' REAL(8) :: rFBAln = -1._dp REAL(8) :: rFBAls = -1._dp REAL(8) :: rEckD = 0._dp REAL(8) :: rArov = -1._dp REAL(8) :: rSFak = -1._dp VOID, POINTER :: pKVNa ! this should point to typeKUGS or typeTORS etc... REAL(8) :: rAriv = 0._dp INTEGER :: iMaNv = 0 CONTAINS PROCEDURE, PUBLIC::setVAM1 => setVAM1_sub END TYPE typeVAM1
Does someting like a void pointer exist or someone has an other idea to solve this?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A couple of options. a CLASS(*) pointer can point to any type. It carries the type info with it. Another option is to use type C_PTR from ISO_C_BINDING, use C_LOC to assign it and C_F_POINTER to "cast" to the desired type. An issue with CLASS(*) is that if you want to use the pointer you will have to do so within a SELECT TYPE construct.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
A couple of options. a CLASS(*) pointer can point to any type. It carries the type info with it. Another option is to use type C_PTR from ISO_C_BINDING, use C_LOC to assign it and C_F_POINTER to "cast" to the desired type. An issue with CLASS(*) is that if you want to use the pointer you will have to do so within a SELECT TYPE construct.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As shown in the original post, the two types (typeKUGS and typeTORS) look the same, only the values of components seem to differ, implying two object instances of the same type. Can you not look into this and check whether a TYPE(..) component in typeVAM1 would be a better choice?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FortranFan wrote:
As shown in the original post, the two types (typeKUGS and typeTORS) look the same, only the values of components seem to differ, implying two object instances of the same type. Can you not look into this and check whether a TYPE(..) component in typeVAM1 would be a better choice?
Yeah the example is simplified, my fault. The other types are looking totally different.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve Lionel (Ret.) wrote:
A couple of options. a CLASS(*) pointer can point to any type. It carries the type info with it. Another option is to use type C_PTR from ISO_C_BINDING, use C_LOC to assign it and C_F_POINTER to "cast" to the desired type. An issue with CLASS(*) is that if you want to use the pointer you will have to do so within a SELECT TYPE construct.
Thanks once again. I will give the class(*) a try.
---------------------------
Trying:
!+------------------------------------------------------------------------+ SUBROUTINE findSuperelement_sub(this, cANam, lIsFound, SU) IMPLICIT NONE CLASS(typeSIP), INTENT(IN) :: this CHARACTER(4), INTENT(IN) :: cANam LOGICAL, INTENT(OUT) :: lIsFound CLASS(*), POINTER, INTENT(OUT) :: SU(:) TYPE(typeKOZE), TARGET :: KOZE lIsFound = .FALSE. CALL this%findKOZE(cANam, lIsFound, KOZE) IF (lIsFound) THEN ALLOCATE(TYPE(typeKOZE)::SU(1)) SELECT TYPE(SU) TYPE IS (typeKOZE) SU(1) => KOZE CLASS DEFAULT WRITE(*,*) 'eleganter Error' END SELECT RETURN END IF
!+------------------------------------------------------------------------+ SUBROUTINE findSuperelement_sub(this, cANam, lIsFound, SU) IMPLICIT NONE CLASS(typeSIP), INTENT(IN) :: this CHARACTER(4), INTENT(IN) :: cANam LOGICAL, INTENT(OUT) :: lIsFound CLASS(*), POINTER, INTENT(OUT) :: SU TYPE(typeKOZE), TARGET :: KOZE lIsFound = .FALSE. CALL this%findKOZE(cANam, lIsFound, KOZE) IF (lIsFound) THEN SU => KOZE RETURN END IF END SUBROUTINE findSuperelement_sub
I tried the concept but I guess I still do not understand it fully. This is my try. The pointer pKOZE => KOZE is pointing correctly, but the allocaten of the CLASS(*) SU is not working. Any suggestions what I am doing wrong?
I found online this example
class(*), pointer :: v1, v2(:) type(person), target :: p1 real, pointer :: r1(:) v1 => p1 allocate(real :: v2(10)) select type (v2) type is (real) r1 => v2 class default stop 'Error in type selection' end select
SOURCE: http://www.training.prace-ri.eu/uploads/tx_pracetmo/AdvFTN_handout.pdf
so the select type construct has to be used just in the case I have to allocate an array?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The first subroutine in #5 should not compile. It has syntax that attempts to pointer assign to an array element. Array elements in Fortran are never pointers.
In the first subroutine, `SU` is a pointer array. It can be pointed at other arrays - `su => some_other_array`.
If you want an array that has a pointer for each element, then the array needs to be of a derived type with a pointer component.
type :: t ! Pointer to a scalar of any type. class(*), pointer :: item => null() end type t type(t) :: array(2) type(x), target :: some_scalar type(y), target :: another_scalar array(1)%item => some_scalar array(2)%item => another_scalar
You don't have to use select type to allocate a polymorphic array - depending on the language revision you are targeting (and whether your compiler supports those revisions) other options exist, including perhaps just using an assignment statement.
It isn't totally clear to me what you are trying to do - consider providing more explanation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ianh wrote:
The first subroutine in #5 should not compile. It has syntax that attempts to pointer assign to an array element. Array elements in Fortran are never pointers.
In the first subroutine, `SU` is a pointer array. It can be pointed at other arrays - `su => some_other_array`.
If you want an array that has a pointer for each element, then the array needs to be of a derived type with a pointer component.
type :: t ! Pointer to a scalar of any type. class(*), pointer :: item => null() end type t type(t) :: array(2) type(x), target :: some_scalar type(y), target :: another_scalar array(1)%item => some_scalar array(2)%item => another_scalarYou don't have to use select type to allocate a polymorphic array - depending on the language revision you are targeting (and whether your compiler supports those revisions) other options exist, including perhaps just using an assignment statement.
It isn't totally clear to me what you are trying to do - consider providing more explanation.
By the subroutines in #5 I just try to understand the concept which Lionel explained. His answer was quite short but pointed in the right direction, so I searched for more information and found the last example in #5. I tried to copy the concept . The subrouteine findSuperelement_sub is not complete yet. cANam is a unique string. For this string is searched in different types (for now just all Objects of typeKOZE but there will be more types). Because of this is neccessary that the subroutine findSuperelemnt_sub has the capability to return CLASS(*) because in the subroutine itself its determiend which Object type will be returned.
For this "Superelement" is searched so I can point from the typeVAM1 to it, thats what I wrote in my initial post.

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