- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[fxfortran]program main type type_O integer :: O end type type_O type, extends(type_O) :: type_A real :: A end type type_A class(type_O), POINTER :: my_O type(type_A), TARGET :: my_A1 type(type_A) :: my_A2 my_A1%O = 1 my_A1%A = 1.56 PRINT *,'Assignment: ', my_A1%O, my_A1%A ! Upcast my_O => my_A1 PRINT *,'Upcasting: ', my_O%O my_A2 = TRANSFER(my_O,my_A2) PRINT *,'Downcasting: ', my_A2%O, my_A2%A end program [/fxfortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's trivial, if slightly more verbose, in Fortran 2003:
SELECT TYPE (my_O)
TYPE IS (type_A)
my_A2 = my_O ! in this block, my_O is effectively declared to be type_A
END SELECT
This accomplishes the same thing, but it is different from the code you wrote in that it will not attempt the assignment if the dynamic type of my_O isn't type_A (i.e., it prevents you from shooting yourself in the foot).
The Fortran 2003 construct is also different in that you can execute multiple statements after establishing my_O to be type_A, and you can provide alternative blocks for other types and for the case that my_O isn't any of the types you are testing for. If the expression inside SELECT TYPE is more complicated that a simple name, you must also provide a simple name to stand for it inside the construct.
-Kurt
P.S. In case it isn't clear from what I've already said, although you are not allowed to write my_O%A in code outside this SELECT TYPE, inside the block following TYPE IS (type_A), you are allowed to do so. This would also be true if the guard statement were CLASS IS (type_A).
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If the physical representation of the result is larger than source, the result contains source's bit pattern in its right-most bits; the left-most bits of the result are undefined.
From the Intel Fortran documentation, pertinent to the use of TRANSFER in Line-26:
If the physical representation of the result is larger than source, the result contains source's bit pattern in its right-most bits; the left-most bits of the result are undefined.
Since the type of my_A2 is an extension of that of my_O, the component of the converted type that was not present in the base class has to be undefined.
I have misgivings about Line-22 as well, although I cannot cite the standard on this one. The situation is similar to assigning x :: REAL(4) to y :: REAL(8), causing 29 bits of precision to be lost, and then assigning y to x. The new value of y will be different from the original.
[fxfortran] program loseI could have used y = TRANSFER (x,y) on Line-8, but that could be considered provocative.
real :: x
double precision :: y
y = acos(-1d0)
write(*,10)y
x=y
write(*,10)x
y=x
write(*,10)y
10 format(F20.15)
end
3.141592653589793
3.141592741012573
3.141592741012573[/fxfortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your use of transfer (which I'd think unlikely to work, but transfer scares me at the best of times) doesn't avoid copying as line 26 is still an assignment statement.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It's trivial, if slightly more verbose, in Fortran 2003:
SELECT TYPE (my_O)
TYPE IS (type_A)
my_A2 = my_O ! in this block, my_O is effectively declared to be type_A
END SELECT
This accomplishes the same thing, but it is different from the code you wrote in that it will not attempt the assignment if the dynamic type of my_O isn't type_A (i.e., it prevents you from shooting yourself in the foot).
The Fortran 2003 construct is also different in that you can execute multiple statements after establishing my_O to be type_A, and you can provide alternative blocks for other types and for the case that my_O isn't any of the types you are testing for. If the expression inside SELECT TYPE is more complicated that a simple name, you must also provide a simple name to stand for it inside the construct.
-Kurt
P.S. In case it isn't clear from what I've already said, although you are not allowed to write my_O%A in code outside this SELECT TYPE, inside the block following TYPE IS (type_A), you are allowed to do so. This would also be true if the guard statement were CLASS IS (type_A).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page