- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi, I am trying to allocate an array for different data types using unlimited polymorphic. However, I find it difficult to pass the class(*),allocatable,intent(out) dummy argument to another subroutine with solid data type via "select type". The test code is listed below: (only implement "type is (integer)" as an example)
module m1
implicit none
contains
subroutine s1(x)
class(*),allocatable,intent(out),target :: x(:)
select type(v => x)
type is (integer)
call s2(v) ! s2(x) also fails
class default
stop 123
end select
end subroutine
subroutine s2(x)
integer,allocatable,intent(out) :: x(:)
allocate(x, source = [1,2,3])
end subroutine
end module
Then, I encountered a compilation error:
$ ifort -c m1.F90
m1.F90(12): error #7976: An allocatable dummy argument may only be argument associated with an allocatable actual argument. [V]
call s2(v)
----------------^
compilation aborted for m1.F90 (code 1)
How can I pass the argument and allocate it in the inner subroutine successfully?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Further - the dynamic type of an unallocated object is never going to be integer. You can replace the entire body of subroutine s1 with just 'stop 123'.
What are you trying to do?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The standard does not permit what you seek. The associate-name 'v' in your 's1' subprogram does NOT have the allocatable attribute.
If you delve further into the current language standard for Fortran and what it offers and the limitations that come along, you will find your attempt "to allocate an array for different data types using unlimited polymorphic" is not a good solution to whatever you are after in your program.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank you for the answer.
Therefore, I have to implement a subroutine with allocatable argument for each data type.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Further - the dynamic type of an unallocated object is never going to be integer. You can replace the entire body of subroutine s1 with just 'stop 123'.
What are you trying to do?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your reply.
I find you are right since I cannot pass a integer, allocatable array to this kind of subroutines ... ...
error #8300: If a dummy argument is allocatable or a pointer, and the dummy or its associated actual argument is polymorphic, both dummy and actual must be polymorphic with the same declared type or both must be unlimited polymorphic.
This error will be displayed
I was trying to "get" a unlimited polymorphic dynamic array within a derived type.
Now, it seems that I have to implement several subroutines for all data type one by one
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You *can* pass an integer allocatable array to an integer allocatable dummy argument (that's kind of the only argument you can pass in that circumstance) - but you don't have an integer allocatable array to pass. The associating entity in a select type construct is not allocatable, as FortranFan says. This is sensible, as otherwise you could reallocate the entity to have a different type inside the select type construct, and madness would result.
(Avoiding similar "ha ha - changed the type!" nonsense is also why there is a requirement for matching declared types between dummy and actual if the dummy has the allocatable attribute.)
But... calling select type on an always unallocated object isn't going to do any useful "selection" - the only block that will be selected for execution is the one that best matches the declared type of the selector. Your selector has a declared type of CLASS(*) - the best match if the selector is unallocated is going to be CLASS DEFAULT. Hence - what are you trying to do? Why are you calling SELECT TYPE?
Are you chasing something like:
SUBROUTINE s3(x, desired_type)
CLASS(*), INTENT(OUT), ALLOCATABLE :: x(:)
CHARACTER(*), INTENT(IN) :: desired_type
IF (desired_type == 'I want an integer') THEN
BLOCK
INTEGER, ALLOCATABLE :: tmp(:)
CALL s2(tmp)
x = tmp ! or CALL MOVE_ALLOC(tmp, x)
END BLOCK
END IF
END SUBROUTINE s3
Why is s2 a subroutine? Can it be a function? Imagine...
FUNCTION f2()
INTEGER :: f2(3)
f2 = [1, 2, 3]
END FUNCTION f2
Then the entire block construct in s3 above can be replaced with...
x = f2()
Do we even need a function? The array is just a constant.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for you reply!
I forget the BLOCK grammar, it may also meet my requirement
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@Roadelse wrote:..
Now, it seems that I have to implement several subroutines for all data type one by one
It may help if you fully describe in plain words what you were asked earlier, "What are you trying to do?"
Ostensibly it appears you have recently discovered the support toward object-oriented paradigm in Fortran including its unlimited polymorphism semantics and you are now excited to use it (widely?) for certain generic programming tasks? If so, you may want to rethink your approach, it's fraught.
Moreover with your statement above, "Now, it seems that I have to implement several subroutines for all data type one by one," it would appear you will help yourself with further analysis of what you are trying to do.
Given your statement, "I was trying to "get" a unlimited polymorphic dynamic array within a derived type," you may have been after something like the following (if so, you should still ask yourself why!) but you have now gone overboard when it comes to defining your "unlimited polymorphic dynamic array within a derived type"?
module m
type :: t
private
class(*), allocatable :: foo(:)
contains
procedure :: init
procedure :: output
end type
contains
subroutine init( this, x )
class(t), intent(inout) :: this
class(*), intent(in) :: x(:)
this%foo = x
end subroutine
subroutine output( this )
class(t), intent(in) :: this
character(len=*), parameter :: fmtg = "(*(g0:,1x))"
select type ( foo => this%foo )
type is ( integer )
print fmtg, "integer foo: ", foo
type is ( real )
print fmtg, "real foo: ", foo
type is ( character(len=*) )
print fmtg, "string foo: ", foo
class default
end select
end subroutine
end module
use m, only : t
type(t) :: a
call a%init( [1,2,3] )
call a%output()
call a%init( [ -99.0, 99.0 ] )
call a%output()
call a%init( [ "cat", "dog" ] )
call a%output()
end
C:\temp>ifort p.f /standard-semantics /free
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.9.0 Build 20230302_000000
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.
Microsoft (R) Incremental Linker Version 14.34.31937.0
Copyright (C) Microsoft Corporation. All rights reserved.
-out:p.exe
-subsystem:console
p.obj
C:\temp>p.exe
integer foo: 1 2 3
real foo: -99.00000 99.00000
string foo: cat dog
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page