在Fortran中有一个函数返回一个可以放在作业左侧的参考 [英] Have a function in fortran return a reference that can be placed on the left-hand-side of an assignment
问题描述
module test_mod
隐含无
整数,目标:: a = 1,b = 2,c = 3!一些成员变量
包含
函数get(i)
整数,pointer :: get
整数,intent(in):: i
select case(i)
case(1)
get =>
案例(2)
get => b
案例(3)
get => c
结束选择
结束函数获得
结束模块test_mod
程序测试
使用test_mod
隐式无
整数,指针:: i_p
!>打印出1 2 3
print *,get(1),get(2),get(3)
!>这是我想要的,但我得到错误
!>错误:(1)处的'get'不是变量
get(2)= 5
!>这工作,但不是我想要的
i_p => get(2)
i_p = 5
结束程序测试
有什么办法来完成这种行为;也许我错过了一些属性?我想绕过编写任何setter例程,比如
set(i,value)
,因为它应该模仿数组的外观。
在我的应用程序中,成员变量 a,b,c
实际上是不同大小的数组
a = [a1,a2,a3]
b = [b1,b2]
c = [c1]
,我希望getter get(i,j)
来模拟一个指针矩阵。 b
$ b
j = 1 2 3
i = 1:[[a1,a2,a3],
i = 2 :[b1,b2,XX],
i = 3:[c1,XX,XX]]
b
更新:
我正在使用gfortran(版本5.2.0),部署机器只有从4.6.x开始的版本及更高版本。因此,不幸的是我建议fortran 2008的标准功能无法使用。是否有可能在没有编译器支持它的情况下模仿上述行为?
更新2:
So我结束了实现一个结构如下
类型Vec_t
integer,allocatable,dimension(:) :: vec
结束类型Vec_t
类型(Vec_t),可分配,维度(:),目标::数据
我初始化的是这样的(我在最后提到的三角矩阵应用程序)
pre $ allocate(data(max ))
do i = 1,max
allocate(data(i)%vec(i))
end do
和我访问&通过
print *,data(2)%vec(1)
data(2)%vec (1)= 5
这不正是我之后的事,但对我的应用程序足够好。 / p>
让我们看看您想要做什么:
get(2)= 5
和错误信息
$ b
错误:(1)处的'get'不是变量
这看起来很全面:你不能做你想做的。或者,也许...
get(2)
确实是在Fortran 2003规则下,不是变量。在Fortran 2003中,变量由规则R601和R603给出,它是一个指示符列表。
赋值的左侧必须是一个变量。 / p>
但请看Fortran 2008及其变量的定义。现在一个变量是指定者之一(或与coarrays或复杂部分相关的变量),但也可以是(C602至R602)作为函数引用,其中
应该有一个数据指针结果。
这在Fortran 2008的介绍中进行了总结,详细介绍了扩展在Fortran 2003中,作为
指针函数引用可以表示任何变量定义上下文中的变量。
get(2)
是对具有数据指针结果的函数的引用。 get(2)
然后可能出现在Fortran 2008规则下的赋值语句的左侧。
唉,对Fortran的这种解释是由当前编译器得不到广泛支持:在回答时只是Cray编译器。
这意味着这个答案实际上是说你有两个选择:切换编译器或等到这个特性更广泛。由于这两种方式都可能不切实际,所以您可能需要另一个答案,它提供了一些稍微便于使用的解决方法。
我更喜欢我的链接 由innoSPG给出,因为虽然后者是基于前者,但适当领域的描述指针函数 - 指针函数ref是一个变量稍微更加清晰。不过,这是一个更方便的文件和一个可行的选择。
As stated in the title, I want to directly modify data that I access through a pointer retrieved from a function. Having a reference returned by a function appearing on the l.h.s. of an assignment(=) is no issue in C++ but the following minimal example in fortran errors out:
module test_mod
implicit none
integer, target :: a=1, b=2, c=3 ! some member variables
contains
function get(i)
integer, pointer :: get
integer, intent(in) :: i
select case (i)
case (1)
get => a
case (2)
get => b
case (3)
get => c
end select
end function get
end module test_mod
program test
use test_mod
implicit none
integer, pointer :: i_p
!> prints out 1 2 3
print*, get(1), get(2), get(3)
!> this is what I want but I get the error
!> Error: 'get' at (1) is not a variable
get(2) = 5
!> this works but is not what I want
i_p => get(2)
i_p = 5
end program test
Is there any way to accomplish this behaviour; maybe I'm missing some attributes? I would like to bypass writing any setter routines such as
set(i,value)
since it should mimic the appearance of an array.
In my application, the member variables a,b,c
are actually arrays of different size
a = [a1, a2, a3]
b = [b1, b2]
c = [c1]
and I want the getter get(i,j)
to mimic a matrix of pointers
j = 1 2 3
i = 1: [[a1, a2, a3],
i = 2: [b1, b2, XX],
i = 3: [c1, XX, XX]]
wehre XX
would be referencing to null()
.
Update: I am using gfortran (version 5.2.0) and the deployment machines would have only versions starting from 4.6.x and upwards. Therefore, the suggested fortran 2008 standard features are unfortunately not available to me. Is it possible to mimic the behaviour described above without having a compiler supporting it out of the box?
Update 2: So I ended up implementing a structure as follows
type Vec_t
integer, allocatable, dimension(:) :: vec
end type Vec_t
type(Vec_t), allocatable, dimension(:), target :: data
which I initialise like this (my triangular matrix application I mention at the end)
allocate(data(max))
do i=1,max
allocate(data(i)%vec(i))
end do
and I access & write to it through
print*, data(2)%vec(1)
data(2)%vec(1) = 5
which is not precisely what I was after but good enough for my application.
Let's look at what you want to do:
get(2)=5
and the error message
Error: 'get' at (1) is not a variable
That looks pretty comprehensive: you can't do what you want. Or, perhaps...
get(2)
is indeed, under the rules of Fortran 2003, not a variable. In Fortran 2003 a variable is given by the rules R601 and R603, which is a list of designators.
The left-hand side of an assignment must be a variable.
But look at Fortran 2008 and its definition of a variable. Now a variable is either one of those same designators (or ones related to coarrays or complex parts), but it could also (C602 to R602) be a function reference which
shall have a data pointer result.
This is summarized in the introduction of Fortran 2008, detailing the extensions over Fortran 2003, as
A pointer function reference can denote a variable in any variable definition context.
get(2)
is a reference to a function that has a data pointer result. get(2)
then may appear on the left-hand side of an assignment statement under the rules of Fortran 2008.
Alas, this interpretation of Fortran is not widely supported by current compilers: at the time of answering just the Cray compiler.
This means that this answer is really saying that you have two options: switch compiler or wait until this feature is more widespread. As both of these are likely impractical, you probably want another answer which gives something slightly more portable as a workaround.
I prefer my link to that given by innoSPG, as although this latter is based on the former, the description of the appropriate field "Pointer functions - pointer function ref is a variable" is slightly more clear. This is, though, a more accessible document and a viable alternative.
这篇关于在Fortran中有一个函数返回一个可以放在作业左侧的参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!