2013-06-12 12 views
7

Kurz definieren, tut, warum diese Arbeit:eine modulare Art innerhalb eines generischen Paket

generic 
    Max : in Positive; 
package Modular_Gen_Issue is 
    procedure Foo; 
private 
    type Mod_Thing is mod Max; -- NOK 
    type Int_Thing is new Integer range 0 .. Max; -- OK 

end Modular_Gen_Issue; 

Mit Compilation:

$ gnatmake modular_gen_issue.ads 
gcc-4.4 -c modular_gen_issue.ads 
modular_gen_issue.ads:6:26: non-static expression used for modular type bound 
modular_gen_issue.ads:6:26: "Max" is not static constant or named number (RM 4.9(5)) 
gnatmake: "modular_gen_issue.ads" compilation error 
$ 

Wie kann ich in einer einzigen Zahl passieren und es verwenden, eine definieren Modularer Typ?

Und ja, es muss ein Modultyp sein!

+1

Nachdem ich ein bisschen damit beschäftigt bin, ja, würde ich gerne wissen, wie es auch geht! :-) Wenn es hier keine Freude gibt, versuchen Sie vielleicht comp.lang.ada, zumindest um einen Grund von einigen der Sprachanwälte zu bekommen, die sich dort aufhalten. –

Antwort

10

Sorry, Sie können nicht. Wann immer Sie einen modularen Typ deklarieren, muss der Modul ein statischer Wert sein, d. H. Ein Wert, den der Compiler dann und dort genau herausfinden kann. Und das funktioniert nicht. Dies gilt für viele Teile von Typdeklarationen, insbesondere Teile, die der Compiler benötigt, um herauszufinden, wie viele Bits ein Objekt sein muss, oder andere Merkmale über die Repräsentation eines Objekts. Andererseits muss in Int_Thing die obere Grenze des Bereichs nicht statisch sein (der Compiler weiß bereits, dass Int_Thing genauso dargestellt wird wie eine Ganzzahl, und der Bereich wird für die Überprüfung der Grenzen verwendet, aber nicht verwendet um zu bestimmen, wie groß ein Int_Thing sein wird).

Wenn dies eine reale Situation ist, und Sie müssen eine generische, die modulare Typen unterschiedlicher verarbeiten kann, können Sie die modulare Art machen können, selbst ein allgemeiner Parameter:

generic 
    type Mod_Thing is mod <>; 
package Modular_Gen_Issue is ... 

(PS Der Bereich der Mod_Thing in Ihrem Beispiel würde 0..max-1, nicht 0..max sein)

+0

Da der Compiler weiß, wie viele Bits ein positives ist, und seine obere Grenze (max), und kennt eine untere Grenze der Modultypen ist 0, ich sehe immer noch nicht, wie dies anders als das Beispiel int_thing ist. – NWS

+3

Der Compiler kennt die obere Grenze (max) nicht an dem Punkt, an dem er die Typdeklaration sieht, weil Sie den generischen Wert nicht instanziiert haben und maximal einen Wert angegeben haben. Und ja, es muss dies wissen, wenn es das Generische zuerst verarbeitet, bevor Sie es instanziieren. Generika sind nicht wie C-Makros, in denen nur der Text gespeichert wird und erst dann betrachtet wird, wenn Sie das Makro erweitern. Generika müssen die Regeln befolgen, noch bevor Sie sie instanziieren. – ajb

+2

Ein anderer Kommentar: Der große Unterschied zu Int_Thing besteht darin, dass Int_Thing von einem vorhandenen Typ (Integer) abgeleitet ist und der Compiler die Größe des Typs auf die gleiche Größe anpasst, von der er abgeleitet wurde. '0 .. Max' fügt Grenzen ein, prüft aber nicht die Größe. Beim Erstellen eines vollständig neuen nicht abgeleiteten Typs benötigt der Compiler jedoch Informationen, die sich auf die Größe auswirken, um statisch zu sein. Wenn Sie sagen, Typ Int_Thing ist Bereich 0 .. Max, das wäre auch illegal. – ajb

3

Neben was AJB schrieb, die folgende Nutzung Ihrer generischen Paket betrachten.

procedure Foo (Bar : in Positive) is 
    package Instance is new Modular_Gen_Issue (Max => Bar); 
begin 
    null; 
end Foo; 

Hier ist die Das Paket Instance wird mit einem nicht statischen Wert erstellt, der sich bei jedem Aufruf von Foo ändern kann. Da Ada dies zulässt, muss der Compiler erwarten, dass ein Parameter einer generischen Einheit nicht statisch ist. Deshalb können Sie Ihren Modultyp dort nicht deklarieren, obwohl Sie Ihr Paket mit einem statischen Wert instanziieren könnten.

AJB Vorschlag erweitern, können Sie tun:

generic 
    type Mod_Thing_Base is mod <>; 
package Modular_Gen_Issue is 
    type Mod_Thing is new Mod_Thing_Base; 
end Modular_Gen_Issue; 

Auf diese Weise können Sie primitive Operationen von Mod_Thing definieren (die Sie nicht direkt, indem sie als Parameter tun könnte).

Verwandte Themen