Вопрос:

Класс Fortran (*) в результате функции

function class return fortran

1734 просмотра

1 ответ

738 Репутация автора

Я столкнулся с ошибкой, связанной с функцией, описанной в этом посте.

Проблема возникает потому, что я пытаюсь вернуть тип, соответствующий типам ввода. Кто-нибудь может предложить решение? У меня изначально была функция для каждого типа, а затем универсальный интерфейс для группировки их в одно имя. Сейчас я пытаюсь поместить все в одну функцию, используя полиморфизм.

Вот ошибка, которую дает мне gfortran.

gfortran -o build/lib/foul.o -c -ffree-form -g -J./build/lib lib/foul.f
lib/foul.f:471.45:

Function cassign (expr, a, b, wrn) Result (c)

Я попытался использовать выделяемый массив. В основной программе я тогда делаю

Character (len=65), Allocatable :: sc(:)
Integer, Allocatable :: ic(:)
Real, Allocatable :: rc(:)

Allocate (sc(1))
Allocate (ic(1))
Allocate (rc(1))

sc = cassign (ra < rb, sa, sb)
ic = cassign (ra < rb, ia, ib)
rc = cassign (ra < rb, ra, rb)

Это возвращает следующую ошибку

gfortran -o build / utests / test_foul.o -c -ffree-form -g -J./build/lib utests / test_foul.f utests / test_foul.f: 315.7:

sc = cassign (ra < rb, sa, sb)
     1
Error: Can't convert CLASS(*) to CHARACTER(1) at (1)
utests/test_foul.f:316.7:

ic = cassign (ra < rb, ia, ib)
     1
Error: Can't convert CLASS(*) to INTEGER(4) at (1)
utests/test_foul.f:317.7:

  rc = cassign (ra < rb, ra, rb)
       1
Error: Can't convert CLASS(*) to REAL(4) at (1)



                                         1
Error: CLASS variable 'c' at (1) must be dummy, allocatable or pointer
lib/foul.f:495.10:

      c = a
      1

Error: Nonallocatable variable must not be polymorphic in intrinsic
assignment at (1) -    check that there is a matching specific subroutine 
for '=' operator
lib/foul.f:497.10:

      c = b
      1

Вот функция, которую я кодировал. Переменные aи bмогут быть любыми из типов Character, integer или real. И тип вывода должен соответствовать входам, aи b функция type_match (a, b)возвращает true, если два типа совпадают, иначе false.

Function cassign (expr, a, b, wrn) Result (c)

  Logical, Intent(in) :: expr
  Class (*), Intent(in) :: a, b
  Logical, Intent (out), Optional :: wrn

  Class (*) :: c  

  Logical :: warn, tma, tmb 

  !!$ Perform warning tests (performs type matching).
  If (Present (wrn)) Then

    !!$ Matching input types. 
    tma = type_match (a, b)
    if (tma) Then

      tmb = type_match (a, c)

      !!$ Matching input and output types.
      If (tmb) Then
        If (expr) Then
          c = a
        Else
          c = b
        End If
        wrn = .False.

      !!$ Warning: Non-matching types.
      Else
        wrn = .True.
      End If

    Else

      wrn = .True.

    End If

  Else

    If (expr) Then
      c = a
    Else
      c = b
    End If

  End If

End Function cassign
Автор: Zeus Источник Размещён: 15.11.2014 10:58

Ответы (1)


3 плюса

18413 Репутация автора

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

Первое, на что следует обратить внимание, это то, что, как говорится в сообщении об ошибке, для полиморфной переменной (такой как c) без фиктивного аргумента эта переменная должна иметь атрибут pointeror allocatable. Здесь имеет смысл для результата функции быть allocatable.

После добавления allocatableатрибута вы, похоже, испытываете две вещи, связанные с назначением выделяемой полиморфной переменной: один раз в функции, устанавливающей результат, и один раз с использованием результата функции.

Версия gfortran, которую вы используете, (по-видимому) не поддерживает внутреннее назначение полиморфных переменных. Вы можете использовать эквивалент, который, возможно, имеет намерение еще яснее:

allocate (c, source=a)  ! You may also need to provide bounds for c
                        ! for some gfortran.

Это решение проблемы присвоения в функции.

Однако с помощью функции result вы теперь возвращаете полиморфный результат. Это означает, что переменная, принимающая присваивание, также должна быть полиморфной, или присваивание не должно быть внутренним. Это

Ошибка: невозможно преобразовать CLASS (*) в INTEGER (4) в (1)

ошибка при попытке внутреннего присваивания.

Или сделайте все полиморфным, придерживайтесь обобщений или используйте определенное назначение. Упрощенный пример следует для последнего случая. [Отрегулируйте и вытяните при необходимости.]

module hello_bob
  interface assignment(=)
    module procedure int_equal_func_class
  end interface

contains

  subroutine int_equal_func_class(a,b)
    integer, intent(out) :: a(:)
    class(*), intent(in) :: b(:)

    select type (b)
      type is (integer)
        a = b
    end select
  end subroutine int_equal_func_class

   function func(a)
     class(*), intent(in) :: a(:)
     class(*), allocatable :: func(:)

     ! No intrinsic assignment supported, also see note about bounds
     allocate(func, source=a)
   end function func

end module hello_bob

program bob
  use hello_bob
  integer i(4)

  i=func([1,2,3,4])
  print*, i

end program bob
Автор: francescalus Размещён: 16.11.2014 12:33
Вопросы из категории :
32x32