Конфликт между определенным назначением и внутренним назначением (с помощью nagfor)?

Внутреннее полиморфное присвоение является недавней особенностью некоторых компиляторов Фортрана (например, ifort 18, nagfor 6.2), которая недоступна в более старых версиях (например, ifort 17, gfortran 6.3). Хорошо известное решение, которое работает с этими более старыми версиями, состоит в том, чтобы использовать определенное назначение, как в примере ниже (взято и адаптировано из книги Чиверса и Слайтхолма):

module deftypes  
   type, abstract :: shape_t  
      integer :: x = 0, y = 0  
   end type shape_t  

   type, extends(shape_t) :: circle_t  
      integer :: radius = 0  
   end type circle_t  

   interface assignment(=)
      module procedure generic_shape_assign
   end interface   

contains  
   subroutine generic_shape_assign ( lhs, rhs )  
      class(shape_t),              intent(in ) :: rhs  
      class(shape_t), allocatable, intent(out) :: lhs  
      print*,' --> in generic_shape_assign'  
      allocate(lhs, source = rhs)  
   end subroutine generic_shape_assign
end module deftypes  

program check_assign  
   use deftypes  
   implicit none  
   class(shape_t), allocatable :: myshape
   type (circle_t)             :: mycirc1, mycirc2  

   mycirc1 = circle_t ( 1, 2, 3 )    

   print*,'A polymorphic assignment: myshape = mycirc1'  
   myshape = mycirc1  

   print*,'An intrinsic assignment: mycirc2 = mycirc1'   
   mycirc2 = mycirc1
end program check_assign

Этот пример компилируется и хорошо работает с ifort 15.0.3 и gfortran 6.3.0. Но с nagfor 6.2 я получаю следующую ошибку во время компиляции (для строки mycirc2=mycirc1):

Error: check_assign.f90, line 41: Incorrect data type CIRCLE_T (expected SHAPE_T) for argument LHS (no. 1) of GENERIC_SHAPE_ASSIGN  

Мне не понятно, почему этот компилятор пытается использовать определенное присваивание в инструкции mycirc2 = mycirc1 в то время как эти две переменные не являются выделяемыми полиморфными.

Конечно, если я удалю определенное назначение, оно будет работать с nagfor, но не с другими старыми компиляторами. Есть идеи, откуда появилась эта ошибка и как ее обойти?

1 ответ

Я считаю, что компилятор правильно отклонить эту программу. Однако, если у вас есть контракт на поддержку с NAG, я настоятельно рекомендую попросить их принять мои комментарии как окончательные.

Я покажу свои рассуждения.

Понятно, что ссылка на конкретную процедуру generic_shape_assign лайк

type(circle_t) mycirc1, mycirc2
call generic_shape_assign(mycirc2, mycirc1)

не является действительным. Это не удается, потому что фактический аргумент mycirc2 соответствует выделенному полиморфному фиктивному аргументу lhs:

  • не подлежит распределению;
  • не имеет того же объявленного типа, что и соответствующий фиктивный аргумент;
  • не полиморфный.

В сообщении об ошибке, которое вы цитируете, говорится об отказе программы за нарушение этой секунды.

Итак, это означает, что generic_shape_assign не является допустимой конкретной процедурой (для этой ссылки) с общей спецификацией assignment(=), право? И, таким образом, не определено присвоение, и компилятор должен вернуться к внутреннему присваиванию?

Здесь вещи становятся мутными (по крайней мере, для меня).

Я думаю, что конкретная подпрограмма generic_shape_assign выбран для определенного назначения, и поэтому компилятор корректен, чтобы отклонить вашу программу, потому что вы не вызываете эту конкретную подпрограмму правильно.

Давайте посмотрим дальше, используя Fortran 2008 7.2.1.4, где есть определение того, когда оператор присваивания является определенным оператором присваивания.

Чтобы решить, будет ли подпрограмма generic_shape_assign определяет определенный оператор присваивания mycirc2=mycirc1 мы смотрим на данные моменты:

  1. generic_shape_assign это подпрограмма с двумя фиктивными аргументами (lhs а также rhs Вот);
  2. блок интерфейса дает generic_shape_assign общая спецификация assignment(=);
  3. lhs (типа shape_t) совместим с типом mycirc2 (динамического типа circle_t); rhs так же;
  4. нет параметров типа для фиктивных или фактических аргументов;
  5. ранги (будучи скалярными) фиктивных и фактических аргументов совпадают.

Мы выполняем все требования для этого, являющегося определенным назначением: не существует требования, в котором говорится, что определенное назначение требует, чтобы выбранная подпрограмма вызывалась!

В итоге:

Мне не понятно, почему этот компилятор пытается использовать определенное присваивание в инструкции mycirc2 = mycirc1 в то время как эти две переменные не являются выделяемыми полиморфными.

Потому что то, используется ли определенное присваивание, не связано с тем, являются ли левая и правая части полиморфными или выделяемыми.

Наконец, я думаю, что диагностическое сообщение от компилятора может быть улучшено независимо от того, правильны ли мои рассуждения или нет.

Другие вопросы по тегам