2016-09-22 24 views
6

Tôi đang cố gắng để vượt qua một thủ tục chung như một đối số thực tế để một hàm:Đi qua một thủ tục chung để một chức năng như là đối số thực tế

module mymod 
implicit none 

interface func 
    module procedure :: func1 
    module procedure :: func2 
endinterface func 

contains 

real function func1(x) 
    real,intent(in) :: x 
    func1 = 2*x 
endfunction func1 

real function func2(x,y) 
    real,intent(in) :: x 
    real,intent(in) :: y 
    func2 = 2*x + 3*y 
endfunction func2 

real function func3(func,x,y) 
    interface 
    real function func(x,y) 
     real,intent(in) :: x 
     real,intent(in) :: y 
    endfunction func 
    endinterface 
    real,intent(in) :: x 
    real,intent(in) :: y 
    func3 = func(x,y) 
endfunction func3 

endmodule mymod 

program myprogram 
use mymod 
implicit none 
write(*,*)func3(func,2.,3.) 
endprogram myprogram 

gfortran 6.2.0 ghi chú rằng tôi không thể làm điều này:

test.f90:43:16: 

write(*,*)func3(func,2.,3.) 
       1 
Error: GENERIC procedure ‘func’ is not allowed as an actual argument at (1) 

Tương tự, với ifort 17:

test.f90(39): error #8164: A generic interface name shall not be used as an actual argument. [FUNC] 
write(*,*)func3(func,2.,3.) 
----------------^ 
test.f90(39): error #6637: When a dummy argument is a function, the corresponding actual argument must also be a function. [FUNC] 
write(*,*)func3(func,2.,3.) 
----------------^ 
compilation aborted for test.f90 (code 1) 

tôi đọc qua 2008 mục chuẩn trên gen giao diện ric và tôi không thể tìm thấy hạn chế như vậy. Tôi cũng không thể nghĩ ra một lý do tại sao trình biên dịch sẽ không thể giải quyết giao diện chung tại thời gian biên dịch. Ruột của tôi nói với tôi rằng điều này có thể thực hiện được, nhưng tôi có thể không có cách tiếp cận đúng. Bạn có biết cách tuân thủ tiêu chuẩn để làm điều này không?

Trả lời

5

Không, điều này không được phép. Trên thực tế, bạn thậm chí không thể chuyển các hàm INTRINSIC chung như các đối số giả.

Cách tuân thủ tiêu chuẩn là sử dụng trực tiếp các chức năng cụ thể phù hợp. Với hàm INTRINSIC, đôi khi bạn phải viết một trình bao bọc cho đúng loại, khi cụ thể không có tên chuẩn.

Ví dụ:

call integrate(derf,0.,1.) 

    contains 
    function derf(x) 
     real(dbl) :: derf 
     real(dbl), intent(in) :: x 
     derf = erf(x) 
    end function 
    end 

là cần thiết nếu bạn muốn vượt qua chính xác thực kép (hoặc bất kỳ khác) phiên bản của erf() vì không có chức năng cụ thể có sẵn.

+1

Luôn rõ ràng và đến điểm, cảm ơn. – milancurcic

+6

Tôi sẽ bình luận rằng việc sử dụng các chức năng cụ thể sẽ trở thành không chuẩn trong Fortran 2015. Tại thời điểm đó sẽ không có cách nào để chuyển một hàm nội tại như một đối số thủ tục và sẽ phải sử dụng phương thức trình bao để tuân thủ các tiêu chuẩn. (Tôi cũng lưu ý rằng không có tên cụ thể nào cho nội tại đã được thêm vào kể từ Fortran 95.) –

1

Tiêu chuẩn Fortran không cho phép người dùng vượt qua các thủ tục chung làm đối số. Để truyền các hàm/chương trình con nội tại, người ta phải sử dụng các thủ tục trình bao bọc do người dùng định nghĩa.

module mymod 

    ! Explicit typing only 
    implicit none 

    ! Declare procedure interface 
    interface 
     function my_func(x, y) result (return_value) 
     real, intent(in) :: x, y 
     real    :: return_value 
     end function my_func 
    end interface 

contains 

    function func1(x) result (return_value) 
     real,intent(in) :: x 
     real   :: return_value 

     return_value = 2*x 

    end function func1 

    function func2(x, y) result (return_value) 
     real, intent(in) :: x, y 
     real    :: return_value 

     return_value = 2*x + 3*y 

    end function func2 

    function func3(user_defined_func, x, y) result (return_value) 
     procedure(my_func) :: user_defined_func 
     real, intent(in) :: x, y 
     real    :: return_value 

     return_value = user_defined_func(x,y) 

    end function func3 

end module mymod 

program main 

    use ISO_Fortran_env, only: & 
     stdout => OUTPUT_UNIT, & 
     compiler_version, & 
     compiler_options 

    use mymod 

    ! Explicit typing only 
    implicit none 

    write (stdout, *) func3(func2, 2.0, 3.0) 
    write (stdout, *) func3(foo, 2.0, 3.0) 
    write (stdout, *) func3(my_atan2, 2.0, 3.0) 

    print '(/4a/)', & 
    ' This file was compiled using ', compiler_version(), & 
    ' using the options ', compiler_options() 

contains 

    ! A user defined function 
    function foo(x, y) result (return_value) 
     real, intent(in) :: x, y 
     real    :: return_value 

     return_value = 42 

    end function foo 

    ! A wrapper function to invoke the intrinsic atan2 
    function my_atan2(x, y) result (return_value) 
     real, intent(in) :: x, y 
     real    :: return_value 

     return_value = atan2(x,y) 

    end function my_atan2 

end program main 

mang

gfortran -std=f2008ts -o main.exe mymod.f90 main.f90 
./main.exe 
    13.0000000  
    42.0000000  
    0.588002622  

This file was compiled using GCC version 6.1.1 20160802 using the options -mtune=generic -march=x86-64 -std=f2008ts 
Các vấn đề liên quan