On Monday, November 12, 2018 at 7:47:49 PM UTC+9,
edmondo.g...@gmail.com wrote:
> Similar result with ifort, but better error message.
> As far as I understood it, it is saying that the expression ( v1 // v2 ) is no more an allocatable and so it cannot be passed to an allocatable argument:
>
> testSpe.f90(28): error #7976: An allocatable dummy argument may only be argument associated with an allocatable actual argument.
> v = (v1 // v2) // v3 ! error (*2)
> ------------^
> compilation aborted for testSpe.f90 (code 1)
>
> ifort version 17.04
Thanks very much for trying with ifort-17 (which I don't have access). The error message
does seem to suggest that the (v1 // v2) is not a (named) object with
the ALLOCATABLE attribute, so my "cat" routine is probably not invoked
for the second "//".
But this means that, with the above approach, one cannot write an
expression like v1 // (v2 // v3) to control the order of association
(unless one introduces intermediate variables like vtmp = v2 // v3; v = v1 // vtmp).
# Interestingly, PGI2017.4 (<-- sorry not the latest one...) with -Mallocatable=03
compiles (v1 // v2) // v3 successfully and gives the same result as v1 // v2 // v3.
---
Another attempt is to wrap an allocatable array into a type. Then, additional
parentheses seem to work. But clearly, this is more verbose than directly
defining such operators for allocatable arrays.
module utils
implicit none
interface operator (//)
module procedure cat_myarr
endinterface
type myarr_t
integer, allocatable :: x(:)
endtype
contains
function cat_myarr( a, b ) result( res )
type(myarr_t), intent(in) :: a, b
type(myarr_t) :: res
allocate( res % x( 0 ) )
if ( allocated( a % x ) ) res % x = [ res % x, a % x ]
if ( allocated( b % x ) ) res % x = [ res % x, b % x ]
endfunction
end
subroutine test()
use utils
implicit none
type(myarr_t) :: v1, v2, v3, ans1, ans2, ans3
v1 % x = [1]
! v2 % x = [2, 3]
v3 % x = [4, 5, 6]
ans1 = v1 // v2 // v3
ans2 = ( v1 // v2 ) // v3
ans3 = v1 // (( v2 // v3 ))
print *, "ans1 = ", ans1 % x
print *, "ans2 = ", ans2 % x
print *, "ans3 = ", ans3 % x
end
program main
call test()
end
Result (gfortran-8.2 and PGI2017.4):
ans1 = 1 4 5 6
ans2 = 1 4 5 6
ans3 = 1 4 5 6