fortran66のブログ

fortran について書きます。

assign (=) operator の overload が elemental で自動 allocate 出来ない件

Fortan90 以降、単項、二項、代入演算子の新規定義や overload ができるようになったわけですが、Fortran95 以降導入されたユーザー定義要素型サブルーチンおよび Fortran2003 以降導入された allocated 型配列の自動割り付けと組み合わせると、代入操作がうまくゆかないようです。

これが Fortran 規格によるものなのか、intel fortran 固有の実装によるものなのか、判断に苦しみます。ただなんとなく規格の隙間に落ち込んだような気がします。

overload する前の代入演算子 = は、Fortran2003 から、allocatable な割り付け配列に対して、割り付けと代入を同時に自動実行してくれますが、overload した後のものは、subroutine に置き換えられるので、それができないようになっています。elemental subroutine の場合、引数はスカラーでなければならないので、allocatable 属性をつけてもスカラーの allocation になってしまい、elemental 属性による配列出力とはならないのが問題の気がします。

単項演算子で配列を出力してそれを overload 前の代入演算子で代入する方法なら望みの結果が得られますが、単なる代入文で表せないのがいとあさまし。

    module m_test
      implicit none
      interface operator (.op.)
        module procedure :: f_minus 
      end interface
      
      interface assignment(=)
        module procedure :: s_minus
      end interface
    contains
      pure elemental character function f_minus(i)
        integer, intent(in) :: i
        write(f_minus, '(i1)') i
      end function f_minus  
      
      pure elemental subroutine s_minus(output, input)
        character, intent(out) :: output
        integer  , intent(in ) :: input
        write(output, '(i1)') input
      end subroutine s_minus  
    end module m_test
!  
    program tests
      use m_test
      implicit none
      character, allocatable :: test(:)
      test = .op. [1,2,3,4,5]
      print *, test
      deallocate(test)
      !
      test = [1,2,3,4,5,6,7]
      print *, test
      deallocate(test)
      !
      call s_minus(test, [1,2,3,4,5,6])
      print *, test
      deallocate(test)
      stop
    end program tests

実行結果 Vista の場合。

f:id:fortran66:20131211015625g:plain

XPの場合は NULL が割り付けられて見かけ上正常終了します。