有没有办法有条件地设置 public 数据结构的类型?
Is there a way to conditionally set the type of a public data structure?
有没有办法有条件地设置 public 数据结构?
例如:
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是两种不同的数据structures/derived类型。
除了引入更多public变量之外,还有什么好的设置方法吗?
谢谢!
我看到两个选项。
- 这可以在运行时改变吗?然后,您可能需要稍后在代码中的其他任何地方访问相同的
DATA
的唯一原因是因为 DATA_TYPE_A
和 DATA_TYPE_B
具有基本相同的 API。这是一个典型的 object-oriented 编程模式示例:您希望两种数据类型共享相同的 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
- 是否应该在编译时修复(
parameter
化)?然后,编译器 pre-processor 将是最有用的。例如,对于 C pre-processor,您将有:
#define DATATYPE_IS_A
#ifdef DATATYPE_IS_A
type(DATA_TYPE_A), parameter :: DATA = [...]
#else
type(DATA_TYPE_B), parameter :: DATA = [...]
#endif
后一个选项在 编译之前执行,即数据类型是强制执行的,永远不能更改。
有没有办法有条件地设置 public 数据结构?
例如:
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是两种不同的数据structures/derived类型。
除了引入更多public变量之外,还有什么好的设置方法吗?
谢谢!
我看到两个选项。
- 这可以在运行时改变吗?然后,您可能需要稍后在代码中的其他任何地方访问相同的
DATA
的唯一原因是因为DATA_TYPE_A
和DATA_TYPE_B
具有基本相同的 API。这是一个典型的 object-oriented 编程模式示例:您希望两种数据类型共享相同的 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
- 是否应该在编译时修复(
parameter
化)?然后,编译器 pre-processor 将是最有用的。例如,对于 C pre-processor,您将有:
#define DATATYPE_IS_A
#ifdef DATATYPE_IS_A
type(DATA_TYPE_A), parameter :: DATA = [...]
#else
type(DATA_TYPE_B), parameter :: DATA = [...]
#endif
后一个选项在 编译之前执行,即数据类型是强制执行的,永远不能更改。