2013-12-07 2 views
3

Я пытаюсь определить процедуру interface d как процедуру привязки по типу в определении Fortran type, но, похоже, она не работает так, как можно было бы ожидать. Рассмотрим следующий модуль:сопряженные процедуры привязки типа в Fortran

module example_module 
implicit none 
private 

interface add_them 
    module procedure add_them_integer,add_them_real 
end interface add_them 

type, public :: foo 
    integer, private :: a=1,b=2 
    real, private :: c=4.,d=5. 
contains 
    procedure, public :: add => add_them 
end type foo 

contains 
subroutine add_them_integer(self,x) 
class(foo), intent(in) :: self 
integer, intent(in) :: x 
print *,self%a+self%b+x 
end subroutine add_them_integer 

subroutine add_them_real(self,x) 
class(foo), intent(in) :: self 
real, intent(in) :: x 
print *,self%c+self%d+x 
end subroutine add_them_real 
end module example_module 

и соответствующую программу, которая использует модуль:

program example 
use example_module 
implicit none 
type(foo) :: foofoo 
call foofoo%add(1) 
call foofoo%add(2.) 
end program example 

Я бы ожидать, что это компилировать и результаты должны быть 4 и 11. Тем не менее, gfortran сообщает следующее сообщение об ошибке:

procedure, public :: add => add_them 
     1 
Error: 'add_them' must be a module procedure or an external procedure with an explicit interface at (1) 

обходной заключается в использовании generic процедуры типа переплета вместо interface г один, так что модуль следующим образом:

module example_module 
implicit none 
private 

type, public :: foo 
    integer, private :: a=1,b=2 
    real, private :: c=4.,d=5. 
contains 
    generic, public :: add => add_them_integer,add_them_real 
    procedure, private :: add_them_integer,add_them_real 
end type foo 

contains 
subroutine add_them_integer(self,x) 
class(foo), intent(in) :: self 
integer, intent(in) :: x 
print *,self%a+self%b+x 
end subroutine add_them_integer 

subroutine add_them_real(self,x) 
class(foo), intent(in) :: self 
real, intent(in) :: x 
print *,self%c+self%d+x 
end subroutine add_them_real 
end module example_module 

Это работает должным образом. Однако я не могу использовать процедуру generic. Вышеприведенное является просто упрощенным примером для демонстрации проблемы, но в моем фактическом коде «add_them» не может быть процедура generic, потому что «foo» на самом деле является производным типом, а «add_them» переопределяет процедуру, определенную в родительском типе; gfortran (по крайней мере) не разрешает generic процедуры, переопределяющие базовые процедуры. Чтобы обойти это ограничение, я подумал, что вместо этого следует использовать interface, но, как вы можете видеть в приведенном выше примере, хотя «add_them» определен правильно, компилятор жалуется, что «add_them» должен быть процедурой модуля или внешней процедурой с явный интерфейс ".

Любая помощь будет оценена по достоинству; заранее спасибо.

ответ

2

Ошибка gfortran для вашего первого раздела кода верна. Способ создания общих привязок соответствует вашему разделу «работает как ожидается».

Если родительский тип имеет конкретную привязку с определенным именем, вы не можете повторно использовать это имя в расширениях, кроме как переопределить конкретную привязку.

Если вы хотите add (обратите внимание, что имя add_them не отображается во втором случае), чтобы быть общей привязкой в ​​расширениях, а затем сделать его общим обязательным в родительском.

+0

Строго говоря, то, что я пытался сделать, это обходить ограничение «вы не можете переопределять не общие процедуры с помощью общих» и пытались использовать сопряженную процедуру для этой цели. Я закончил работу, как сказал IanH, также делая родительскую процедуру общей. Для этого также необходимо добавить конструкцию 'select type' в родительскую процедуру (на самом деле это то, чего я хотел избежать), но она работает. – Pap

+0

Я все еще не вижу, почему процедура сопряжения не может быть процедурой, связанной с типом, что делает процедуры «generic» единственным решением в приведенном выше примере. Fortran 2003/2008 даже позволяет переопределять имена типов с помощью сопряженной процедуры, в основном создавая «конструктор». Почему бы не использовать их как процедуры привязки типов? – Pap

+0

То, что вы называете «сопряженной процедурой», является общим интерфейсом. Эквивалент для привязки является общей привязкой. Процедуры, которые реализуют привязки, имеют требования к ним вокруг переданных аргументов и т. Д. Если вы собираетесь использовать в автономном обобщенном синтаксисе интерфейса для указания общих привязок, тогда эти ограничения должны будут работать через этот синтаксис. Это было бы довольно грязно. – IanH

Смежные вопросы