2013-10-06 18 views
6

Es scheint, dass Fortran 90 keine benannten Konstanten in abgeleiteten Datentypen zulässt. Ist das wahr? Der folgende Code funktioniert nicht.Benannte Konstanten als Komponenten eines abgeleiteten Datentyps

Der Compiler sagt Parameteranweisung ist in abgeleiteten Typdefinitionen nicht erlaubt.

Wenn ich das parameter Schlüsselwort entfernen, funktioniert alles gut. Aber wie kann ich dann sicherstellen, dass die Komponente a nicht woanders verändert wird?

+0

* ... wie kann ich sicherstellen, dass 'a' an keiner anderen Stelle geändert wird? * Sie meinen, es nicht zu benutzen? : D –

+0

In Fortran 2003 gibt es viele andere Möglichkeiten. Es kann eine private Variable mit Setter/Getter-Methoden sein. Es kann eine geschützte Komponente sein ... –

Antwort

3

Machen Sie die Konstante (den Parameter) eine lokale Entität des Hauptprogramms und nicht den Typ. Wenn Sie mehr Kontrolle über die Sichtbarkeit und den Gültigkeitsbereich des Bezeichners für die Konstante haben möchten, setzen Sie die Konstante in ein Modul.

+0

Danke. Sie bieten alternative Lösungen, die mein Problem lösen. Können Sie ein Yay oder Nein für das Parameterkonstrukt angeben, das in einem abgeleiteten Datentyp nicht erlaubt ist? Brauchen Sie eine Bestätigung, um zu wissen, dass sie nicht compilerspezifisch ist. – user1318806

+0

Es ist eine direkte Folge der Regeln der Sprache. Es ist nicht compilerspezifisch. – IanH

5

Gemäß der Norm ist es nicht erlaubt. Das Komponente Attribut Spezifizierer kann nur pointer und dimension für Fortran 90/95 (Abschnitt 4.4.1), zusätzlich allocatable in Fortran 2003 (Abschnitt 4.5.3) und zusätzlich codimension und contiguous für Fortran 2008 (Abschnitt 4.5. 4.1).

Sie können die Dokumente here erhalten.

Ich stieß auf ein ähnliches Problem mit dem target Spezifizierer, der auch nicht erlaubt ist.

EDIT: Warum nicht versuchen private Komponenten?

module typedef 
    type :: my_type 
    integer, private :: a_int = 1 
    real(kind(1.d0)) :: b 
    contains 
    procedure :: a 
    end type my_type 

contains 
    function a(complex_type) 
    class(my_type),intent(in) :: complex_type 
    integer :: a 
    a = complex_type%a_int 
    end function 
end module 

program my_prog 
    use typedef 
    implicit none 

    type (my_type) :: complex_type 

    complex_type%b = 2.d0 ! This should work 
    write(*,*) complex_type%a(), complex_type%b 

! complex_type%a_int = 3 ! This should fail 

end program my_prog 
+0

Großartig! Privat ist der Weg zu gehen. Nur eine Klarstellung. In Ihrem Code-Code über 'class (my_type) sollte stattdessen intention (in) :: complex_type' type (my_type), intent (in) :: complex_type 'heißen. Zumindest in Fortran 90! – user1318806

+0

Beginnend mit Fortran 2003 soll das Dummy-Argument * polymorph (4.3.1.3) genau dann sein, wenn der Typ, der definiert wird, erweiterbar ist * ('my_type' ist erweiterbar).Wenn Sie also 'type' anstelle von' class' verwenden, wird bei Verwendung von Fortran 2003 und höher ein Fehler auftreten. –

2

Die Frage ist: Warum Sie das tun wollen?

Stellen Sie sich vor, Sie möchten ein Array mit 1000 Werten erstellen my_type. Das Ergebnis wäre, dass der Wert a 1000 mal gespeichert worden wäre. Dies ist eine Verschwendung von fast 4 kb Speicher (unter der Annahme int4). Der bessere Weg wäre, den Parameter in einem entsprechenden Modul zu definieren.

Btw, in dem Buch Modern Fortran von Clerman und Spector, Regel Nummer 133 besagt, dass Sie jeden abgeleiteten Typ in einem eigenen Modul definieren sollten. Dies wäre ein großartiger Ort für eine solche Konstante.

+0

Ich werde nicht mehr als eine Kopie haben. Ich verwende es so, wie Sie in c aufzählen würden. Ich habe ein System von Differentialgleichungen. Anstatt auf den Vektor als 'Y (0), Y (1)' usw. zu verweisen, möchte ich sie als 'Y (var1), Y (var2)' usw. bezeichnen. 'var1, var2' usw. sind konstante Parameter im neuen Datentypen. – user1318806

0

Sie können es als privat definieren und eine get() - Funktion, aber keine set() - Funktion erzeugen. Auf diese Weise werden Ihre Daten gut gekapselt.