Конфликт между определенным назначением и внутренним назначением (с nagfor)? - PullRequest
0 голосов
/ 20 ноября 2018

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

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

В этом примере компилируется и работаетхорошо с ифортом 15.0.3 и гфортраном 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 Ответ

0 голосов
/ 22 ноября 2018

Я считаю, что компилятор корректен, чтобы отклонить эту программу.Однако, если у вас есть контракт на поддержку с 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, в то время как эти две переменные не могут быть распределенными полиморфными.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...