2013-06-12 16 views
7

W skrócie, dlaczego robi to dzieło:Definiowanie typu modułowego w opakowaniu generycznego

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; 

Z kompilacji:

$ 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 
$ 

Jak mogę przekazać w jednym szeregu i użyć go zdefiniować typ modułowy?

I tak, to musi być typ modułowy!

+1

Po tym, jak powiodło mi się to trochę, tak, chciałbym wiedzieć, jak to zrobić! :-) Jeśli nie ma tutaj radości, może spróbuj comp.lang.ada, przynajmniej po to, aby uzyskać powód od niektórych prawników, którzy tam przebywają. –

Odpowiedz

10

Niestety, nie możesz. Za każdym razem, gdy zadeklarujesz typ modularny, moduł musi być wartością statyczną, tj. Wartością, którą kompilator może znaleźć w danym momencie. A to nie działa. Dotyczy to wielu części deklaracji typu, w szczególności części potrzebnych kompilatorowi do określenia liczby bitów, które obiekt musi zawierać, lub innych cech dotyczących reprezentacji obiektu. Z drugiej strony, w Int_Thing, górna granica zakresu nie musi być statyczna (kompilator już wie, że Int_Thing będzie reprezentowany tak samo jak liczba całkowita, a zakres jest używany do sprawdzania granic, ale nie jest używany określić, jak duże będzie Int_Thing).

Jeśli jest to sytuacja prawdziwym życiu i trzeba ogólnym, które mogą obsługiwać różnych rodzajów modułowych, może być w stanie zrobić sam typ modułową ogólny parametr:

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

(PS Zakres Mod_Thing w przykładzie byłoby 0..Max-1, nie 0..Max)

+0

Ponieważ kompilator wie, ile bitów jest dodatnich, a jego górna granica (max) i zna dolną granicę typów modułów jest równa 0, nadal nie widzę, jak to jest inaczej niż w przykładzie int_thing. – NWS

+3

Kompilator nie zna górnej granicy (max) w miejscu, w którym widzi deklarację typu, ponieważ nie utworzono instancji generycznej i podano maksymalną wartość. I tak, to musi wiedzieć o tym, kiedy najpierw przetwarza dane ogólne, zanim je utworzysz. Generics nie są podobne do makr C, gdzie po prostu przechowuje tekst i nie patrzy na niego, dopóki nie rozszerzysz makra. Generics muszą przestrzegać zasad nawet zanim je stworzysz. – ajb

+2

Jeszcze jedna uwaga: duża różnica z Int_Thing polega na tym, że Int_Thing pochodzi z istniejącego typu (Integer), a kompilator sprawi, że rozmiar tego typu będzie taki sam jak ten, z którego pochodzi. '0 .. Max' dodaje sprawdzanie granic, ale nie zmienia rozmiaru. Ale podczas tworzenia zupełnie nowego typu niepochodzącego kompilator potrzebuje informacji, które wpływają na rozmiar statyczny. Jeśli powiedziałeś, że 'typ Int_Thing jest w zakresie 0 .. Max', to byłoby również nielegalne. – ajb

3

Oprócz co AJB napisał Rozważmy następujący wykorzystanie pakietu rodzajowego.

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

Tutaj pakiet Instance jest tworzony z niestatyczną wartością, która może ulec zmianie przy każdym wywołaniu do Foo. Ponieważ Ada na to pozwala, kompilator musi oczekiwać, że dowolny parametr jednostki ogólnej będzie niestatyczny. Dlatego nie możesz zadeklarować swojego typu modułowego, nawet jeśli możesz utworzyć instancję pakietu z wartością statyczną.

Rozszerzanie sugestię AJB, można zrobić:

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

ten sposób można zdefiniować prymitywne operacje Mod_Thing (które nie można zrobić, biorąc go jako parametr bezpośrednio).

Powiązane problemy