有没有办法有条件地设置公共数据结构的类型?

发布于 2025-02-01 10:04:21 字数 711 浏览 4 评论 0原文

有没有办法有条件地设置公共数据结构?

例如:

MODULE EXAMPLE

  USE DATA_TYPE_Define, ONLY: DATA_TYPE_A, DATA_TYPE_B
  USE PARAMETER,        ONLY: CaseAisTrue

  ! Disable all implicit typing
  IMPLICIT NONE

  ! ------------
  ! Visibilities
  ! ------------
  ! Everything private by default
  PRIVATE
  ! The shared data
  PUBLIC :: DATA

  ! ------------------------------------------------
  ! The shared data 
  ! ------------------------------------------------

  IF (CaseAisTrue) Then
     TYPE(DATA_TYPE_A), SAVE :: DATA
  ELSE
     TYPE(DATA_TYPE_B), SAVE :: DATA
  END IF


CONTAINS
  ...

data_type_a和data_type_b是两个不同的数据结构/派生类型。

除了引入更多的公共变量外,还有什么好方法可以设置它吗?

谢谢你!

Is there a way to conditionally set a public data structure?

For example:

MODULE EXAMPLE

  USE DATA_TYPE_Define, ONLY: DATA_TYPE_A, DATA_TYPE_B
  USE PARAMETER,        ONLY: CaseAisTrue

  ! Disable all implicit typing
  IMPLICIT NONE

  ! ------------
  ! Visibilities
  ! ------------
  ! Everything private by default
  PRIVATE
  ! The shared data
  PUBLIC :: DATA

  ! ------------------------------------------------
  ! The shared data 
  ! ------------------------------------------------

  IF (CaseAisTrue) Then
     TYPE(DATA_TYPE_A), SAVE :: DATA
  ELSE
     TYPE(DATA_TYPE_B), SAVE :: DATA
  END IF


CONTAINS
  ...

Where DATA_TYPE_A and DATA_TYPE_B are two different data structures/derived types.

Is there any good way to set this up besides introducing more public variables?

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

半衾梦 2025-02-08 10:04:21

我看到了两个选项。

  1. 这个可以在运行时更改吗?然后,您可能需要访问相同的data以后在代码中的其他任何地方访问相同的唯一原因是因为data_type_adata_type_b基本上具有相同的API 。这是一个典型的示例面向对象的编程模式:您希望两种数据类型共享相同的API:
! The base class
type, abstract, public :: DATA_TYPE
end type DATA_TYPE

type, public, extends(DATA_TYPE) :: DATA_TYPE_A
   [...]
end type DATA_TYPE_A

type, public, extends(DATA_TYPE) :: DATA_TYPE_B
   [...]
end type DATA_TYPE_B

如果您需要在要访问的数据类型之间继续切换,则可以为它们提供两个单独的变量:

! Actual shared data, here or elsewhere
type(DATA_TYPE_A), target, SAVE :: DATA_A
type(DATA_TYPE_B), target, SAVE :: DATA_B

并指向它们使用指针:

class(DATA_TYPE), public, pointer :: DATA => null()

! Set pointer
subroutine set_data(mode)
   integer, intent(in) :: mode
   select case (mode)
     case (1);     DATA => DATA_A
     case (2);     DATA => DATA_B
     case default; nullify(DATA)
   end select  
end subroutine set_data

否则,如果您不经常更改它,则可以使用多态分配,这将更加优雅:

! Actual shared data
class(DATA_TYPE), allocatable :: DATA

并在需要时分配正确的类型:

! Polymorphic allocation
subroutine set_data(mode)
   integer, intent(in) :: mode
   integer :: ierr
   
   ! Deallocate first
   deallocate(DATA,stat=ierr) ! don't stop if not already allocated

   select case (mode)
     case (1);     allocate(DATA,source=DATA_A) 
     case (2);     allocate(DATA,source=DATA_B)
     case default; return
   end select  
end subroutine set_data
  1. 是否应修复此操作(parameter> ized)编译时间?然后,编译器预处理器将是最有用的。例如,使用C前处理器,您将拥有:

#define DATATYPE_IS_A


#ifdef DATATYPE_IS_A
   type(DATA_TYPE_A), parameter :: DATA = [...]
#else
   type(DATA_TYPE_B), parameter :: DATA = [...]
#endif

后一个选项是在编译之前执行的,即,该数据类型已执行,无法更改。

I see two options.

  1. Can this change at runtime? Then, the only reason you may need to access the same DATA anywhere else in the code later is because DATA_TYPE_A and DATA_TYPE_B have essentially the same API. This is a typical example object-oriented programming pattern: you want the two data types share the same API:
! The base class
type, abstract, public :: DATA_TYPE
end type DATA_TYPE

type, public, extends(DATA_TYPE) :: DATA_TYPE_A
   [...]
end type DATA_TYPE_A

type, public, extends(DATA_TYPE) :: DATA_TYPE_B
   [...]
end type DATA_TYPE_B

If you need to keep switching between the data types you're accessing, you can have two separate variables for them:

! Actual shared data, here or elsewhere
type(DATA_TYPE_A), target, SAVE :: DATA_A
type(DATA_TYPE_B), target, SAVE :: DATA_B

And point to them using a pointer:

class(DATA_TYPE), public, pointer :: DATA => null()

! Set pointer
subroutine set_data(mode)
   integer, intent(in) :: mode
   select case (mode)
     case (1);     DATA => DATA_A
     case (2);     DATA => DATA_B
     case default; nullify(DATA)
   end select  
end subroutine set_data

Otherwise, if you don't change it that often, you could just use polymorphic allocation, that would be more elegant:

! Actual shared data
class(DATA_TYPE), allocatable :: DATA

And allocate the right type whenever needed:

! Polymorphic allocation
subroutine set_data(mode)
   integer, intent(in) :: mode
   integer :: ierr
   
   ! Deallocate first
   deallocate(DATA,stat=ierr) ! don't stop if not already allocated

   select case (mode)
     case (1);     allocate(DATA,source=DATA_A) 
     case (2);     allocate(DATA,source=DATA_B)
     case default; return
   end select  
end subroutine set_data
  1. Should this be fixed (parameterized) at compile time? Then, a compiler pre-processor will be most useful. For example, with the C pre-processor, you'd have:

#define DATATYPE_IS_A


#ifdef DATATYPE_IS_A
   type(DATA_TYPE_A), parameter :: DATA = [...]
#else
   type(DATA_TYPE_B), parameter :: DATA = [...]
#endif

This latter option is performed before compilation, i.e., that datatype is enforced and can never be changed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文