Domanda

Sto cercando di scrivere un pacchetto generico e una delle operazioni richieste è quello di checksum i record di dati ricevuti nel corso di un autobus. Il tipo di record varia ed è un parametro generico. Tuttavia ogni tentativo di accedere ai membri del parametro generico causano un errore di compilazione.

L'errore ... (Ada 95 GNAT 2009)

file.adb:XX no selector "Data" for private type "The_Transfer_Type" defined at file.ads:YY

La dichiarazione ...

generic
  type The_Transfer_Type is private;
  SIZE : Integer;
package CC_Test_Channel is
  function Checksum(Msg : The_Transfer_Type) return Integer;
end package

E il corpo ...

function Checksum(Msg : The_Transfer_Type) return Integer is
  Sum : Integer := 0;
begin
  -- calculate the checksum
  for i in 1 .. SIZE loop
    Sum := Sum + Integer(Msg.Data(i));
  end loop;
  return Sum;
end Checksum;
È stato utile?

Soluzione

Quando si specifica che un parametro generico è un tipo privato, beh, Ada si assume vuoi dire che: -)

vale a dire. non si ha accesso ai suoi componenti. Ada non è " anatra digitato", quindi è irrilevante se non si sa che un tipo di creare un'istanza potrebbe effettivamente possedere un determinato campo. (Come ci si aspetterebbe la funzione di checksum a funzionare se The_Transfer_Type parametro fosse istanziato con, diciamo, Integer?)

Un modo per affrontare questo è quello di fornire anche una funzione di accesso come parametro per il generico che recupererà i dati necessari per, in questo caso, calcolare la somma di controllo. Per esempio:.

generic
   type The_Transfer_Type is private;
   with function Get_Checksummable_Data_Item
           (Msg : The_Transfer_Type;
            I   : Integer) return Integer;
   SIZE : Integer;

package CC_Test_Channel is
   function Checksum(Msg : The_Transfer_Type) return Integer;
end CC_Test_Channel;

Il corpo è quindi:

function Checksum(Msg : The_Transfer_Type) return Integer is
   Sum : Integer := 0;
begin
   -- calculate the checksum
   for i in 1 .. SIZE loop
      Sum := Sum + Get_Checksummable_Data(Msg, I);
   end loop;
   return Sum;
end Checksum;

La funzione si fornisce per Get_Checksummable_Data è quindi specifico per The_Transfer_Type e semplicemente restituisce il valore selezionato dai campi che compongono il The_Transfer_Type.

Ci sono un certo numero di altri modi per installare questo come bene, come fornire un tipo di matrice non vincolato come un parametro formale generico e una funzione formale di recuperarlo - questo consente di ottenere anche eliminare il parametro formale esplicito MISURA . Oppure si potrebbe scrivere una funzione di checksum () come una delle operazioni sul tipo che si sta istanziazione CC_Test_Channel con, e quindi avere:

with function Calculate_Checksum(Msg : The_Transfer_Type) return Integer;

come uno dei formali generici.

Un passo indietro, e pensare alle possibilità ...

Altri suggerimenti

(spostato da un commento, come questo ha a lungo)

Ada (95 e versioni successive) supporta flussi. Diversamente flussi C ++, che sono praticamente per la conversione di stringhe, flussi Ada sono intese come un meccanismo generale per eseguire operazioni su dati (tipicamente I / O).

Ogni oggetto Ada ha attributi 'Write e 'Read. Ci sono alcuni flussi lingua dotazione (per i file I / O), ma si ha anche la possibilità di creare il proprio derivando da Ada.Streams.Root_Stream_Type . Se si scrive il proprio flusso in questo modo, ci sono alcune routine di basso livello che ti danno l'accesso diretto ai dati.

Questo consente di scrivere i propri flussi di eseguire operazioni come me O, compressione / dati, o nel tuo caso forse checksum dei dati dal bus prima di caricarla in variabili (via 'Read). L'ho fatto io stesso in passato per implementare una funzionalità di registrazione / riproduzione per il nostro software in tempo reale. Ho guardato dentro per la compressione una volta di troppo (abbiamo finito per non aver bisogno della compressione).

generic 
  type The_Transfer_Type is private; 
  ...

Il codice di cui sopra significa che il cliente può fornire qualsiasi tipo sognano per The_Transfer_Type (fintanto che non è "limitata"). Ciò significa anche che il vostro generico sa assolutamente nulla circa il tipo, se non che asignment è disponibile.

Con i farmaci generici Ada non v'è una sorta di una relazione inversa tra il numero di diversi tipi di oggetti possono essere forniti per un parametro generico, e quali operazioni sono avilable al generico su quegli oggetti. Ad esempio, il tipo più aperto sarebbe is limited private. Si potrebbe fornire qualsiasi tipo whatsover per uno di quelli. Tuttavia, il generico può fare quasi nulla con esso. Anche l'assegnazione non sarebbe disponibile.

Togliete la "limitata" e si può fare asignments con esso, ma solo i tipi che possono essere assegnati possono essere forniti. All'altro estremo, si potrebbe definire come: type The_Transfer_Type is (<>) e poi si potrebbe fornire un numero intero tipo enumerato, e guadagnerebbe cose come 'first. Andando ancora oltre, si potrebbe fare type The_Transfer_Type is range <>, e che ci si guadagna la possibilità di fare operazioni matematiche interi, ma sarebbe solo in grado di fornire interi tipi numerici.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top