Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
945 views
in Technique[技术] by (71.8m points)

fortran - Generic interfaces and operator overloading - how to set procedure from generic interface block to be private in module?

My IDE is: Code::Blocks 20.03 ( MinGW 9.2.0 )

This is my code:

module mod_kompleks

  use, intrinsic :: iso_c_binding, only : rp => c_double

  implicit none

  type, public :: kom_bro

    real(rp), private :: rea
    real(rp), private :: img

    contains

      procedure, pass(kdt), private :: kom_bro_ini
      procedure, pass(kdt),  public :: uzm_rea => uzm_pod_rea
      procedure, pass(kdt),  public :: uzm_img => uzm_pod_img
      procedure, pass(kdt), private :: kom_bro_sab

      generic, public :: operator(+) => kom_bro_sab

  end type kom_bro

  interface kom_bro

    module procedure kom_bro_kon

  end interface kom_bro

  private :: kom_bro_kon

contains

  function kom_bro_kon( bro_rea, bro_img ) result( bro )

    real(rp), intent(in) :: bro_rea
    real(rp), intent(in) :: bro_img
    type(kom_bro)        :: bro

    call bro%kom_bro_ini(bro_rea, bro_img)

  end function kom_bro_kon

  subroutine kom_bro_ini(kdt, dio_rea, dio_img)

    class(kom_bro), intent(out) :: kdt
     real(rp),      intent(in)  :: dio_rea
     real(rp),      intent(in)  :: dio_img

     kdt%rea = dio_rea
     kdt%img = dio_img

  end subroutine kom_bro_ini

  function uzm_pod_rea( kdt ) result( rez )

    class(kom_bro), intent(in) :: kdt
     real(rp)                  :: rez

     rez = kdt%rea

  end function uzm_pod_rea

  function uzm_pod_img( kdt ) result( rez )

    class(kom_bro), intent(in) :: kdt
     real(rp)                  :: rez

     rez = kdt%img

  end function uzm_pod_img

  function kom_bro_sab( kdt, bro ) result( rez )

    class(kom_bro), intent(in) :: kdt
    class(kom_bro), intent(in) :: bro
     type(kom_bro)             :: rez

     rez%rea = kdt%rea + bro%rea
     rez%img = kdt%img + bro%img

  end function kom_bro_sab

end module mod_kompleks

program kompleksni_broj

  use, non_intrinsic :: mod_kompleks

  implicit none

  type(kom_bro) :: broj_01, broj_02, broj_03

  broj_01 = kom_bro(1.1_rp,2.2_rp)

  print '(1x,f4.2,1x,"j",1xf4.2)', broj_01%uzm_rea(), broj_01%uzm_img()

  broj_02 = kom_bro(3.3_rp,4.4_rp)

  print '(1x,f4.2,1x,"j",1xf4.2)', broj_02%uzm_rea(), broj_02%uzm_img()

  broj_03 = broj_01 + broj_02

  print '(1x,f4.2,1x,"j",1xf4.2)', broj_03%uzm_rea(), broj_03%uzm_img()

end program kompleksni_broj

My intention is to disable access to the kom_bro_sab procedure outside the mod_kompleks module. In case I want to construct a complex number with values for the real and imaginary part in the main program, after typing the word kom I get the opportunity to choose the procedure kon_bro, which of course I wanted, but next to that function I am offered the opportunity to choose the procedure kom_bro_sab. How can I prevent this (I want only the procedure kom_bro_sab and the operator + to be visible)? I will add screenshot of what i got even the type - bound procedure was private: kom_bro_sab

question from:https://stackoverflow.com/questions/65602970/generic-interfaces-and-operator-overloading-how-to-set-procedure-from-generic

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In short

The kom_bro_sab function has (default) access property public which is why you can access kom_bro_sab in your main program.

Explanation

The function kom_bro_sab is exported as any other function would be because its access property is public. This is because by default the access property is public and was not changed here.

Dont be confused by the line procedure, pass(kdt), private :: kom_bro_sab. Here a type-bound procedure kom_bro_sab is defined and which has access property private. Thus, you can only call this property from other type-bound procedures. You should differentiate between the type-bound procedure and the function itself.

Solutions

There are two ways to handle it.

  1. Changing the default access property to private and only explicitly defining the public entities. This also makes it easier when quickly looking through modules to see which entities are actually exported.
module mod_kompleks
  use, intrinsic :: iso_c_binding, only : rp => c_double
  implicit none
  private
  public kom_bro
  
  type kom_bro
...
end module
  1. You could keep at what you were doing by explicitly defining public and private properties. Then you just need to add one line (see the line containing ADDED).
module mod_kompleks
  use, intrinsic :: iso_c_binding, only : rp => c_double
  implicit none
  type, public :: kom_bro
...
  end interface kom_bro
  private kom_bro_kon
  private kom_bro_sab     ! <- ADDED
...
end module

I shortened your code and hope that it is still understandable.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...