fortran66のブログ

fortran について書きます。

万能型 CLASS(*)

昔のFORTRANでは、EQUIVALNECE や COMMON で変数の番地を共有させたり、副プログラムの呼び出しでわざと型の違う変数を渡したり、文字型がなかったので適当な型の変数の中にホレリスで文字データをいれたりして、必要とあらば型を無視して自由にやれたのですが、時代が進んで Fortran90 では型や配列の次元(rank)にうるさくなって、昔より窮屈になりました。

ただチェックなどが厳しくなってからは、明らかに実行時エラーなどが減ったので、型や次元のチェックが有効だったのは間違いありません。とはいえ窮屈すぎると型や次元ごとに内容の重複するサブルーチンなどを用意する必要があるので、別の面倒が増えてきました。

その結果 Fortran95 では 要素型(elemental)サブルーチンが定義できるようになり、次元に関する制約が緩められ、Fortran2003 では動的プログラミング的な要素が導入されて、型チェックが緩くなることになりました。

ここでは Fortran2003 で導入された万能型 class() について書いておきます。class () 型の変数には、どんな型の値も代入できるのですが、使い方が面倒なので備忘録的として。

class (*) の制約

class (*) 型の変数は、必ず allocatable 属性か pointer 属性を持たねばなりません。直接の代入や書き出しもできません。代入は allocate で、出力等の処理は select type ... end select 構文を用います。

    program test
      implicit none
      class (*), allocatable :: a, b, c, d
      allocate(a, source = 1    )
      allocate(b, source = 1.0  )
      allocate(c, source = 1.0d0)
      allocate(d, source = 'one')
      
      call prn(a)
      call prn(b)
      call prn(c)
      call prn(d)
      stop
      
    contains
      subroutine prn(c)
        class (*), intent(in) :: c
        select type (c)
          type is (integer)
            print *, c
          type is ( real(kind(0.0e0)) )
            print *, c
          type is ( real(kind(0.0d0)) )
            print *, c
          type is ( character (*) )
            print *, c
          class default
            print *, 'unknown type'
        end select     
        return
      end subroutine prn  

    end program test

実行結果

           1
   1.000000
   1.00000000000000
 one
続行するには何かキーを押してください . . .

つづく