How to specify procedures to be executed depending on data type of variable

三世轮回 提交于 2019-12-10 11:27:11

问题


I'm writing a module that access images and reads pixel values. The values in the images are usually of different data types (integer(2), integer(4), ...). Up to now, type image is defined in the following way:

type, public :: image
  logical        :: initialized   = .false.
  character(256) :: path          = ""      ! Path to image
  integer        :: dimensions(3) = -1      ! Dimensions of image
  integer        :: datatype      = 0       ! Datatype
  contains
    procedure :: initialize
    procedure :: pxvalues
    procedure :: getMeta
end type image

My question now: Is there a possibility that the program automatically finds the corresponding procedures depending on the data type of the image (stored in variable image%datatype)? E.g. if the data type is integer, the subroutine pxvalues_integer is called during the execution of image%pxvalues.

Thanks!


回答1:


If you are unwilling to change the structure of your code, then the SELECT CASE approach proposed by bdforbes is an option.

Beyond that you may be able to use polymorphism and replace the datatype component by different types that are all extensions of the same parent type. This is the fundamental reason why type bound procedures (the procedure statements after the contains in the type definition) exist, so you might as well use them as intended!

type, public, abstract :: image
  ! Common components to all extensions
  logical        :: initialized   = .false.
  character(256) :: path          = ""      ! Path to image
  integer        :: dimensions(3) = -1      ! Dimensions of image
  contains
    procedure :: initialize
    ! Abstract interface pxvalues_image specified what the interface must
    ! look like.  Deferred attribute means that extensions of image 
    ! must specify a specific procedure for the pxvalues binding.  All 
    ! specific procedures must have the same interface bar the passed 
    ! argument.
    procedure(pxvalues_image), deferred :: pxvalues
    procedure :: getMeta
end type image

abstract interface
  subroutine pxvalues_image(obj, ...)
    import :: image
    class(image), intent(in) :: obj
    ...
  end subroutine pxvalues_image
end interface

! A type for images that have integer2 data.
type, public, extends(image) :: image_integer2
  contains
    procedure :: pxvalues => pxvalues_integer2
end type image_integer2

! A type for images that have integer4 data.
type, public, extends(image) :: image_integer4
  contains
    procedure :: pxvalues => pxvalues_integer4
end type image_integer4

The specific procedures ''pxvalues_integer2'', ''pxvalues_integer4'', etc, then take an initial argument that is of the extension type.

Rather than setting the datatype component, the code that creates the initial "image" object should instead then create the object as the appropriate extension of image, perhaps:

subroutine create_image(object)
  class(image), intent(out), allocatable :: object
  ...
  ! We want an image that for integer2's
  allocate(image_integer2 :: object)

There are implication of this approach that require more knowledge of your code than can be given in isolated example snippets.




回答2:


How about having an actual procedure pxvalues like this:

subroutine pxvalues(this)
    select case (this%datatype)
    case (0)
        call this%pxvalues_integer
    case (1)
        call this%pxvalues_real
    end select
end subroutine



回答3:


If pxvalues is a module procedure defined with an interface, you could do the following:

interface pxvalues ; module procedure &
    pxvalues_integer , &
    pxvalues_real
end interface


来源:https://stackoverflow.com/questions/11539050/how-to-specify-procedures-to-be-executed-depending-on-data-type-of-variable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!