|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
g95 procedure pointers as derived-type components
Hi All, I've been programming in f90/f95 since 1994. I've wanted procedure pointers for a real long time, and I read on another c.l.f posting that g95 has them. So, I've written a little test program that _almost_ compiles. Problem is, how on earth do I provide procedure pointers to the derived-type constructor? My code: module objs abstract interface function myfunc(i) result(rv) integer, intent(in) :: i integer :: rv end function myfunc end interface type, public :: BASE_OBJ integer :: t procedure (myfunc), pointer :: f end type BASE_OBJ contains function x2(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer :: i integer :: rv rv = 2 * ob%t + i return end function x2 function x3(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer :: i integer :: rv rv = 2 * ob%t + i return end function x3 function make_doubler(j) result(rv) type (BASE_OBJ) :: rv integer :: j rv => BASE_OBJ(j, x2) end function make_doubler function make_tripler(j) result(rv) type (BASE_OBJ) :: rv integer :: j rv => BASE_OBJ(j, x3) end function make_tripler end module objs program test use objs d => make_doubler(5) print *, d%f(2) t => make_tripler(5) print *, t%f(2) stop end program test Please note that I knew in advance that the syntax here would fail; I just didn't know what to do... The compiler reports: C:\>g95 victest.f95 In file victest.f95:36 rv => BASE_OBJ(j, x2) 1 Error: Missing actual argument list in function call to 'x2' at (1) In file victest.f95:42 rv => BASE_OBJ(j, x3) 1 Error: Missing actual argument list in function call to 'x3' at (1) C:\> Any advice? THANKS! --vic
type, public :: BASE_OBJ integer :: t procedure (integer), pointer :: f end type BASE_OBJ
On May 11, 1:36 pm, linuxl4.@gmail.com wrote: > type, public :: BASE_OBJ > integer :: t > procedure (integer), pointer :: f > end type BASE_OBJ
I tried this, and the original problem persists. The problem is in the creation of a BASE_OBJ object via the BASE_OBJ constructor. I do not know how to pass the procedure pointer to the BASE_OBJ constructor. Within my function make_doubler(), I attempt to create a BASE_OBJ entity, which requires passing a pointer to the selected function (e.g. x2 or x3). I don't know how to do it. Here's the offending code: the BASE_OBJ type has two components, an integer and a procedure pointer to a function that returns an integer. I have a function 'x2' that I want to associate function make_doubler(j) result(rv) type (BASE_OBJ) :: rv integer :: j rv => BASE_OBJ(j, x2) end function make_doubler And here's the error I get (it's because 'x2' in the constructor call is not provided with any parameters). Is there a syntactic literal for a procedure pointer in the derived-type constructor? Or, can I create the object in another way? THANKS. --v
Hello, Even in Fortran 95, it is to my knowledge not possible to use a pointer or target as an item within a structure constructor for a type with pointer components. I imagine this would extend to procedure pointers, in which case the only way - apart from default initialization - to provide a target is by component resolution: base_obj%f => my_fun Note that in a fully Fortran 2003 conforming implementation it is possible to do argument assignment by keyword. Not all components need to be addressed. This would make type(base_obj) :: my_obj my_obj = base_obj(t=0.0d0) legal. Default initialization for non-referenced components is kept. Regards
Vic.Kel @gmail.com wrote: > On May 11, 1:36 pm, linuxl4. @gmail.com wrote: >> type, public :: BASE_OBJ >> integer :: t >> procedure (integer), pointer :: f >> end type BASE_OBJ > I tried this, and the original problem persists. The problem is in the > creation of a BASE_OBJ object via the BASE_OBJ constructor. I do not > know how to pass the procedure pointer to the BASE_OBJ constructor. > Within my function make_doubler(), I attempt to create a BASE_OBJ > entity, which requires passing a pointer to the selected function > (e.g. x2 or x3). I don't know how to do it. > Here's the offending code: the BASE_OBJ type has two components, an > integer and a procedure pointer to a function that returns an integer. > I have a function 'x2' that I want to associate > function make_doubler(j) result(rv) > type (BASE_OBJ) :: rv > integer :: j > rv => BASE_OBJ(j, x2) > end function make_doubler > And here's the error I get (it's because 'x2' in the constructor call > is not provided with any parameters). Is there a syntactic literal for > a procedure pointer in the derived-type constructor? Or, can I create > the object in another way? > THANKS. > --v
All right, now we're getting closer. Obviously, I needed a default initializer in the type declaration. Now, the problem is when I compile it, I get a different assignment error from g95. I think I'm getting close here... C:\>g95 victest.f95 In file victest.f95:36 rv => BASE_OBJ(t=j) 1 Error: Pointer assignment target is neither TARGET nor POINTER at (1) C:\> The code: module objs abstract interface function myfunc(i) result(rv) integer, intent(in) :: i integer :: rv end function myfunc end interface type, public :: BASE_OBJ integer :: t = 0 procedure (myfunc), pointer :: f => NULL() end type BASE_OBJ contains function x2(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer, intent(in) :: i integer :: rv rv = 2 * ob%t + i return end function x2 function x3(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer, intent(in) :: i integer :: rv rv = 2 * ob%t + i return end function x3 function make_doubler(j) result(rv) type (BASE_OBJ), pointer :: rv integer :: j rv => BASE_OBJ(t=j) ****** HERE'S WHERE IT FAILS rv%f => x2 end function make_doubler function make_tripler(j) result(rv) type (BASE_OBJ), pointer :: rv integer :: j rv => BASE_OBJ(t=j) rv%f => x3 end function make_tripler end module objs program test use objs type (BASE_OBJ), pointer :: d, t d => make_doubler(5) print *, d%f(2) t => make_tripler(5) print *, t%f(2) stop end program test
I have implemented the default initialization, and I'm getting a different error in an assignment statement. This is getting close, I think <grin>... The error: C:\>g95 victest.f95 In file victest.f95:36 rv => BASE_OBJ(t=j) 1 Error: Pointer assignment target is neither TARGET nor POINTER at (1) C:\> The Code: module objs abstract interface function myfunc(i) result(rv) integer, intent(in) :: i integer :: rv end function myfunc end interface type, public :: BASE_OBJ integer :: t = 0 procedure (myfunc), pointer :: f => NULL() end type BASE_OBJ contains function x2(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer, intent(in) :: i integer :: rv rv = 2 * ob%t + i return end function x2 function x3(ob, i) result (rv) type (BASE_OBJ), pointer :: ob integer, intent(in) :: i integer :: rv rv = 2 * ob%t + i return end function x3 function make_doubler(j) result(rv) type (BASE_OBJ), pointer :: rv integer :: j rv => BASE_OBJ(t=j) rv%f => x2 end function make_doubler function make_tripler(j) result(rv) type (BASE_OBJ), pointer :: rv integer :: j rv => BASE_OBJ(t=j) rv%f => x3 end function make_tripler end module objs program test use objs type (BASE_OBJ), pointer :: d, t d => make_doubler(5) print *, d%f(2) t => make_tripler(5) print *, t%f(2) stop end program test THANKS! --v
If rv is a pointer (to a scalar object), you need to first have it point to an existing target, or dynamically allocate it. The structure constructor will *not* do that for you. Once it *is* allocated, you use the standard assignment to provide the target with appropriate values, i.e. rv = base_obj(t=j) Again, if the compiler does not yet support the F2003 keyword/optional parameter syntax, you may need to do rv%t = j anyway. Regards
Vic.Kel @gmail.com wrote: > I have implemented the default initialization, and I'm getting a > different error in an assignment statement. This is getting close, I > think <grin>... > The error: > C:\>g95 victest.f95 > In file victest.f95:36 > rv => BASE_OBJ(t=j) > 1 > Error: Pointer assignment target is neither TARGET nor POINTER at (1) > C:\> > The Code: > module objs > abstract interface > function myfunc(i) result(rv) > integer, intent(in) :: i > integer :: rv > end function myfunc > end interface > type, public :: BASE_OBJ > integer :: t = 0 > procedure (myfunc), pointer :: f => NULL() > end type BASE_OBJ > contains > function x2(ob, i) result (rv) > type (BASE_OBJ), pointer :: ob > integer, intent(in) :: i > integer :: rv > rv = 2 * ob%t + i > return > end function x2 > function x3(ob, i) result (rv) > type (BASE_OBJ), pointer :: ob > integer, intent(in) :: i > integer :: rv > rv = 2 * ob%t + i > return > end function x3 > function make_doubler(j) result(rv) > type (BASE_OBJ), pointer :: rv > integer :: j > rv => BASE_OBJ(t=j) > rv%f => x2 > end function make_doubler > function make_tripler(j) result(rv) > type (BASE_OBJ), pointer :: rv > integer :: j > rv => BASE_OBJ(t=j) > rv%f => x3 > end function make_tripler > end module objs > program test > use objs > type (BASE_OBJ), pointer :: d, t > d => make_doubler(5) > print *, d%f(2) > t => make_tripler(5) > print *, t%f(2) > stop > end program test > THANKS! > --v
Vic.Kel @gmail.com wrote: > ... Problem is, how on earth do I provide procedure > pointers to the derived-type constructor? If I read the F2003 (draft) Standard correctly, in particular 4.5.9 C490, it should be possible. That is, say I have an abstract interface: abstract interface subroutine mysub (a, b) integer :: a, b end subroutine end interface and a derived type which contains a procedure pointer: type mytype_t procedure(mysub), pointer :: pptr end type type(mytype_t) :: pptrs(5) G95 lets me write: pptrs(1)%pptr => mysub1 pptrs(2)%pptr => mysub2 pptrs(3)%pptr => mysub3 pptrs(4)%pptr => mysub4 pptrs(5)%pptr => mysub5 This works fine. According to C490 I should also be able to use a structure constructor to write: pptrs(1) = mytype_t (mysub1) pptrs(2) = mytype_t (mysub2) pptrs(3) = mytype_t (mysub3) pptrs(4) = mytype_t (mysub4) pptrs(5) = mytype_t (mysub5) G95 gives an error message. ("... Expected 'mysub1' ... to be a VARIABLE"). So my take is that g95 still has a bit to go to properly support the feature. An email to Andy might be appropriate... W.
|
 |
 |
 |
 |
|