Modelli in C++Modifica
C++ utilizza modelli per abilitare tecniche di programmazione generiche. La libreria standard C++ include la libreria modello standard o STL che fornisce un framework di modelli per strutture dati e algoritmi comuni. I modelli in C++ possono anche essere utilizzati per la metaprogrammazione dei modelli, che è un modo per pre-valutare parte del codice in fase di compilazione piuttosto che in fase di esecuzione. Utilizzando la specializzazione dei modelli, i modelli C++ sono considerati completi di Turing.,
Technical overviewEdit
Esistono due tipi di modelli: modelli di funzione e modelli di classe. Un modello di funzione è un modello per la creazione di funzioni ordinarie in base ai tipi di parametrizzazione forniti quando istanziati. Ad esempio, la libreria di modelli standard C++ contiene il modello di funzione max(x, y) che crea funzioni che restituiscono x o y, a seconda di quale è più grande., max()
potrebbe essere definito come:
template <typename T>T max(T x, T y) { return x < y ? y : x;}
Specializzazioni di questo modello di funzione, le istanze con specifiche tipologie, può essere definita come una comune funzione:
std::cout << max(3, 7); // Outputs 7.
Il compilatore esamina gli argomenti utilizzati per chiamare max e stabilisce che questa è una chiamata a max(int, int)., Poi crea una versione della funzione in cui l’applicazione di parametri di tipo T è di tipo int, rendendo l’equivalente della seguente funzione:
int max(int x, int y) { return x < y ? y : x;}
Questo funziona se gli argomenti x e y sono numeri interi, stringhe, o qualsiasi altro tipo per il quale l’espressione x < y è sensibile, o, più specificamente, per qualsiasi tipo per il quale l’operatore< è definito. L’ereditarietà comune non è necessaria per l’insieme di tipi che possono essere utilizzati, quindi è molto simile alla digitazione duck., Un programma che definisce un tipo di dati personalizzato può utilizzare l’overloading dell’operatore per definire il significato di < per quel tipo, consentendo così il suo utilizzo con il modello di funzione max (). Anche se questo può sembrare un vantaggio minore in questo esempio isolato, nel contesto di una libreria completa come STL consente al programmatore di ottenere funzionalità estese per un nuovo tipo di dati, semplicemente definendo alcuni operatori per esso., La semplice definizione di< consente di utilizzare un tipo con gli algoritmi standard sort(), stable_sort () e binary_search() o di essere inserito all’interno di strutture dati come set, heap e array associativi.
I modelli C++ sono completamente sicuri in fase di compilazione. A dimostrazione, il complesso di tipo standard non definisce l’operatore<, poiché non esiste un ordine rigoroso sui numeri complessi. Pertanto, max (x, y) fallirà con un errore di compilazione, se x e y sono valori complessi., Allo stesso modo, altri modelli che si basano su < non possono essere applicati a dati complessi a meno che non venga fornito un confronto (sotto forma di funtore o funzione). Ad esempio: Un complesso non può essere utilizzato come chiave per una mappa a meno che non venga fornito un confronto. Sfortunatamente, i compilatori generano storicamente messaggi di errore un po ‘ esoterici, lunghi e inutili per questo tipo di errore. Garantire che un determinato oggetto aderisca a un protocollo di metodo può alleviare questo problema. Le lingue che usano compare invece di < possono anche usare valori complessi come chiavi.,
Il secondo tipo di modello, un modello di classe, estende lo stesso concetto alle classi. Una specializzazione del modello di classe è una classe. I modelli di classe vengono spesso utilizzati per creare contenitori generici. Ad esempio, l’STL ha un contenitore elenco collegato. Per creare un elenco collegato di numeri interi, si scrive list<int>. Un elenco di stringhe è indicato list< string >. Un elenco ha un insieme di funzioni standard ad esso associate, che funzionano per qualsiasi tipo di parametrizzazione compatibile.,
Template specializationEdit
Una potente funzionalità dei modelli di C++è la specializzazione dei modelli. Ciò consente di fornire implementazioni alternative in base a determinate caratteristiche del tipo parametrizzato che viene istanziato. La specializzazione del modello ha due scopi: consentire determinate forme di ottimizzazione e ridurre il rigonfiamento del codice.
Ad esempio, considera una funzione modello sort (). Una delle attività principali che tale funzione fa è scambiare o scambiare i valori in due delle posizioni del contenitore., Se i valori sono grandi (in termini di numero di byte necessari per memorizzarli ciascuno), è spesso più veloce creare prima un elenco separato di puntatori agli oggetti, ordinare quei puntatori e quindi creare la sequenza ordinata finale. Se i valori sono piuttosto piccoli, di solito è più veloce scambiare semplicemente i valori sul posto secondo necessità. Inoltre, se il tipo parametrizzato è già di qualche tipo di puntatore, non è necessario creare un array di puntatore separato., La specializzazione del modello consente al creatore del modello di scrivere implementazioni diverse e di specificare le caratteristiche che i tipi parametrizzati devono avere per ogni implementazione da utilizzare.
A differenza dei modelli di funzione, i modelli di classe possono essere parzialmente specializzati. Ciò significa che una versione alternativa del codice del modello di classe può essere fornita quando alcuni dei parametri del modello sono noti, lasciando altri parametri del modello generici., Questo può essere utilizzato, ad esempio, per creare un’implementazione predefinita (la specializzazione primaria) che presuppone che la copia di un tipo di parametrizzazione sia costosa e quindi creare specializzazioni parziali per i tipi che sono economici da copiare, aumentando così l’efficienza complessiva. I client di tale modello di classe usano solo le specializzazioni di esso senza dover sapere se il compilatore ha utilizzato la specializzazione primaria o una specializzazione parziale in ciascun caso., I modelli di classe possono anche essere completamente specializzati, il che significa che un’implementazione alternativa può essere fornita quando tutti i tipi di parametrizzazione sono noti.
Vantaggi e svantaggimodiFica
Alcuni usi di modelli, come la funzione max (), erano precedentemente riempiti da macro di preprocessore simili a funzioni (un’eredità del linguaggio di programmazione C). Ad esempio, ecco una possibile macro max ():
#define max(a,b) ((a) < (b) ? (b) : (a))
Le macro vengono espanse dal preprocessore, prima della compilazione corretta; i modelli vengono espansi in fase di compilazione., Le macro sono sempre espanse in linea; i modelli possono anche essere espansi come funzioni in linea quando il compilatore lo ritiene appropriato. Pertanto, sia le macro funzionali che i modelli di funzioni non hanno un sovraccarico in fase di esecuzione.
Tuttavia, i modelli sono generalmente considerati un miglioramento rispetto alle macro per questi scopi. I modelli sono sicuri per il tipo. I modelli evitano alcuni degli errori comuni trovati nel codice che fa un uso pesante di macro simili a funzioni, come la valutazione dei parametri con effetti collaterali due volte. Forse la cosa più importante, i modelli sono stati progettati per essere applicabili a problemi molto più grandi delle macro.,
Ci sono quattro svantaggi principali nell’uso dei modelli: funzionalità supportate, supporto del compilatore, messaggi di errore scadenti e codice gonfio:
- I modelli in C++ mancano di molte funzionalità, il che rende spesso impossibile implementarli e utilizzarli in modo semplice. Invece i programmatori devono fare affidamento su trucchi complicati che portano a codice gonfio, difficile da capire e difficile da mantenere. Gli attuali sviluppi negli standard C++ esacerbano questo problema facendo un uso pesante di questi trucchi e costruendo molte nuove funzionalità per i modelli su di essi o con loro in mente.,
- Molti compilatori hanno storicamente scarso supporto per i modelli, quindi l’uso di modelli può rendere il codice un po ‘ meno portabile. Il supporto può anche essere scarso quando un compilatore C++ viene utilizzato con un linker che non è C++-aware, o quando si tenta di utilizzare i modelli oltre i confini della libreria condivisa. La maggior parte dei compilatori moderni, tuttavia, ora ha un supporto template abbastanza robusto e standard, e il nuovo standard C++, C++11, risolve ulteriormente questi problemi.
- Quasi tutti i compilatori producono messaggi di errore confusi, lunghi o talvolta inutili quando vengono rilevati errori nel codice che utilizza i modelli., Questo può rendere i modelli difficili da sviluppare.
- Infine, l’uso di modelli richiede al compilatore di generare un’istanza separata della classe o della funzione templated per ogni permutazione dei parametri di tipo utilizzati con esso. (Questo è necessario perché i tipi in C++ non hanno tutte le stesse dimensioni e le dimensioni dei campi dati sono importanti per il funzionamento delle classi.) Quindi l’uso indiscriminato di modelli può portare a gonfiare il codice, con conseguente eseguibili eccessivamente grandi., Tuttavia, l’uso giudizioso della specializzazione e della derivazione dei modelli può ridurre drasticamente tale rigonfiamento del codice in alcuni casi:
Quindi, la derivazione può essere utilizzata per ridurre il problema del codice replicato perché vengono utilizzati i modelli? Ciò comporterebbe la derivazione di un modello da una classe ordinaria. Questa tecnica si è dimostrata efficace nel frenare il rigonfiamento del codice nell’uso reale. Le persone che non usano una tecnica come questa hanno scoperto che il codice replicato può costare megabyte di spazio di codice anche in programmi di dimensioni moderate.,
— Bjarne Stroustrup, The Design and Evolution of C++, 1994
Le istanze extra generate dai template possono anche far sì che i debugger abbiano difficoltà a lavorare con garbo con i template. Ad esempio, l’impostazione di un punto di interruzione di debug all’interno di un modello da un file di origine può mancare l’impostazione del punto di interruzione nell’istanza effettiva desiderata o può impostare un punto di interruzione in ogni punto in cui il modello viene istanziato.,
Inoltre, poiché il compilatore deve eseguire espansioni di modelli simili a macro e generare istanze diverse di essi in fase di compilazione, il codice sorgente di implementazione per la classe o la funzione basata su modelli deve essere disponibile (ad esempio incluso in un’intestazione) nel codice che lo utilizza. Le classi o le funzioni basate su modelli, inclusa gran parte della libreria di modelli standard (STL), se non incluse nei file di intestazione, non possono essere compilate. (Questo è in contrasto con il codice non basato su modelli, che può essere compilato in binario, fornendo solo un file di intestazione delle dichiarazioni per il codice che lo utilizza.,) Questo può essere uno svantaggio esponendo il codice di implementazione, che rimuove alcune astrazioni e potrebbe limitarne l’uso in progetti closed-source.
Modelli in DEdit
Il linguaggio di programmazione D supporta modelli basati nella progettazione su C++.,La maggior parte degli idiomi del modello C++ verrà trasferita a D senza modifiche, ma D aggiunge alcune funzionalità aggiuntive:
- I parametri del modello in D non sono limitati ai soli tipi e valori primitivi, ma consentono anche valori arbitrari in fase di compilazione (come stringhe e letterali di struttura) e alias a identificatori arbitrari, inclusi altri modelli o istanze di template.
- I vincoli del modello e l’istruzione if statica forniscono un’alternativa al meccanismo di sostituzione di C++non è un errore (SFINAE), simile ai concetti di C++.
- È (…,) l’espressione consente l’istanziazione speculativa per verificare i tratti di un oggetto in fase di compilazione.
- La parola chiave auto e l’espressione typeof consentono l’inferenza del tipo per le dichiarazioni delle variabili e i valori di ritorno delle funzioni, che a loro volta consentono “tipi Voldemort” (tipi che non hanno un nome globale).
I modelli in D usano una sintassi diversa rispetto a C++: mentre in C++ i parametri dei modelli sono racchiusi tra parentesi angolari (Template<param1, param2>),D usa un segno esclamativo e parentesi: Template!(param1, param2).,Ciò evita le difficoltà di analisi del C++ dovute all’ambiguità con gli operatori di confronto.Se c’è un solo parametro, le parentesi possono essere omesse.
Convenzionalmente, D combina le funzionalità di cui sopra per fornire polimorfismo in fase di compilazione utilizzando la programmazione generica basata sui tratti.,Per esempio, un intervallo di input è definito come qualsiasi tipo che soddisfa i controlli effettuati dalla isInputRange, che è definita come segue:
Una funzione che accetta in ingresso varia quindi possibile utilizzare il modello di cui sopra in un modello di vincolo:
auto fun(Range)(Range range) if (isInputRange!Range){ // ...}
Codice generationEdit
In aggiunta al template metaprogramming, D inoltre fornisce diverse funzioni per consentire la compilazione di generazione di codice:
- L’importazione di espressione consente la lettura di un file da disco e utilizzando il suo contenuto come espressione di stringa.,
- La riflessione in fase di compilazione consente di enumerare e ispezionare le dichiarazioni e i loro membri durante la compilazione.
- Gli attributi definiti dall’utente consentono agli utenti di allegare identificatori arbitrari alle dichiarazioni, che possono quindi essere enumerati utilizzando la riflessione in fase di compilazione.
- Compile-Time Function Execution (CTFE) consente di interpretare un sottoinsieme di D (limitato a operazioni sicure) durante la compilazione.
- I mixins di stringhe consentono di valutare e compilare il contenuto di un’espressione di stringa come codice D che diventa parte del programma.,
La combinazione di quanto sopra consente di generare codice basato su dichiarazioni esistenti.Ad esempio, i framework di serializzazione D possono enumerare i membri di un tipo e generare funzioni specializzate per ciascun tipo serializzato per eseguire serializzazione e deserializzazione.Gli attributi definiti dall’utente potrebbero indicare ulteriormente le regole di serializzazione.
L’espressione di importazione e l’esecuzione della funzione in fase di compilazione consentono anche di implementare in modo efficiente i linguaggi specifici del dominio.,Ad esempio, data una funzione che prende una stringa contenente un modello HTML e restituisce un codice sorgente D equivalente, è possibile utilizzarla nel modo seguente:
Genericità in EiffelEdit
Le classi generiche sono state parte di Eiffel dal metodo originale e dal design del linguaggio. Le pubblicazioni della fondazione Eiffel, usano il termine genericità per descrivere la creazione e l’uso di classi generiche.
Basic/Unconstrained genericityEdit
Le classi generiche vengono dichiarate con il loro nome di classe e un elenco di uno o più parametri generici formali., Nel codice seguente, la classe LIST
dispone di un formale generico parametro G
La formale parametri generici sono segnaposto per arbitrario i nomi di classe che saranno fornite al momento della dichiarazione della classe generica è fatto, come mostrato in due generici derivazioni di seguito, dove ACCOUNT
e DEPOSIT
sono altri nomi di classe. ACCOUNT
e DEPOSIT
sono considerati parametri generici reali in quanto forniscono nomi di classe reali per sostituire G
nell’uso effettivo.,
list_of_accounts: LIST -- Account list list_of_deposits: LIST -- Deposit list
All’interno del sistema di tipi Eiffel, sebbene la classeLIST
sia considerata una classe, non è considerata un tipo. Tuttavia, una derivazione generica di LIST
come LIST
è considerata un tipo.
Genericità vincolataedit
Per la classe list mostrata sopra, un parametro generico effettivo che sostituisceG
può essere qualsiasi altra classe disponibile., Per vincolare l’insieme di classi da cui è possibile scegliere i parametri generici effettivi validi, è possibile specificare un vincolo generico. Nella dichiarazione di classe SORTED_LIST
di seguito, il vincolo generico impone che qualsiasi parametro generico effettivo valido sarà una classe che eredita dalla classeCOMPARABLE
. Il vincolo generico assicura che gli elementi di un SORTED_LIST
possano infatti essere ordinati.,
class SORTED_LIST
Generici in JavaEdit
Il supporto per i generici, o “contenitori di tipo T” è stato aggiunto al linguaggio di programmazione Java nel 2004 come parte di J2SE 5.0. In Java, i generici vengono controllati solo in fase di compilazione per la correttezza del tipo. Le informazioni generiche sul tipo vengono quindi rimosse tramite un processo chiamato cancellazione del tipo, per mantenere la compatibilità con le vecchie implementazioni JVM, rendendole non disponibili in fase di runtime., Ad esempio, un elenco<String> viene convertito nell’elenco dei tipi raw. Il compilatore inserisce i cast di tipo per convertire gli elementi nel tipo di stringa quando vengono recuperati dall’elenco, riducendo le prestazioni rispetto ad altre implementazioni come i modelli C++.
Genericità in. NET Edit
I generici sono stati aggiunti come parte di.NET Framework 2.0 nel novembre 2005, sulla base di un prototipo di ricerca di Microsoft Research iniziato nel 1999. Anche se simile ai generici in Java, .,NET generics non applica la cancellazione del tipo, ma implementa i generici come meccanismo di prima classe nel runtime utilizzando reification. Questa scelta di progettazione fornisce funzionalità aggiuntive, come consentire la riflessione con la conservazione di tipi generici, oltre ad alleviare alcune delle limitazioni della cancellazione (come l’impossibilità di creare array generici). Ciò significa anche che non vi è alcun impatto sulle prestazioni da lanci di runtime e conversioni di boxe normalmente costose., Quando i tipi primitivi e di valore vengono utilizzati come argomenti generici, ottengono implementazioni specializzate, consentendo raccolte e metodi generici efficienti. Come in C++ e Java, i tipi generici nidificati come Dictionary<string, List<int>> sono tipi validi, tuttavia sono sconsigliati per le firme dei membri nelle regole di progettazione dell’analisi del codice.
.,NET consente sei varietà di vincoli di tipo generico utilizzando la parola chiave where, tra cui limitare i tipi generici ai tipi di valore, alle classi, ai costruttori e all’implementazione delle interfacce. Di seguito un esempio con un vincolo di interfaccia:
Il MakeAtLeast() metodo permette di operare su matrici, con elementi di tipo generico T. Il metodo del vincolo di tipo indica che il metodo è applicabile a qualsiasi tipo T che implementa il generico IComparable<T> interfaccia., Ciò garantisce un errore in fase di compilazione, se il metodo viene chiamato se il tipo non supporta il confronto. L’interfaccia fornisce il metodo generico CompareTo (T).
Il metodo precedente potrebbe anche essere scritto senza tipi generici, semplicemente usando il tipo di array non generico. Tuttavia, poiché gli array sono controvarianti, il casting non sarebbe sicuro per il tipo e il compilatore non sarebbe in grado di trovare alcuni possibili errori che altrimenti verrebbero rilevati quando si utilizzano tipi generici. Inoltre, il metodo dovrebbe accedere agli elementi dell’array come oggetti e richiederebbe il casting per confrontare due elementi., (Per tipi di valore come tipi come int questo richiede una conversione di boxe, anche se questo può essere risolto usando la classe Comparer <T>, come si fa nelle classi di raccolta standard.)
Un comportamento notevole dei membri statici in una classe.NET generica è l’istanziazione di membri statici per tipo di runtime (vedi esempio sotto).
Genericità in DelphiEdit
Il dialetto Object Pascal di Delphi ha acquisito generici nella versione Delphi 2007, inizialmente solo con il (ora interrotto) .,NET compiler prima di essere aggiunto al codice nativo nella versione Delphi 2009. La semantica e le capacità di Delphi generics sono in gran parte modellate su quelle dei generici in.NET 2.0, sebbene l’implementazione sia necessariamente molto diversa. Ecco una traduzione più o meno diretta del primo esempio c# mostrato sopra:
Come con c#, i metodi e interi tipi possono avere uno o più parametri di tipo. Nell’esempio, TArray è un tipo generico (definito dalla lingua) e MakeAtLeast un metodo generico., I vincoli disponibili sono molto simili ai vincoli disponibili in c#: qualsiasi tipo di valore, qualsiasi classe, una classe o un’interfaccia specifica e una classe con un costruttore senza parametri. I vincoli multipli fungono da unione additiva.
Genericità in PascalEdit libero
Free Pascal implementava generici prima di Delphi e con sintassi e semantica diverse. Tuttavia, dalla versione FPC 2.6.0, la sintassi in stile Delphi è disponibile quando si utilizza la modalità di linguaggio {mode mode Delphi}. Pertanto, i programmatori Free Pascal sono in grado di utilizzare i generici in qualsiasi stile preferiscano.,
Delphi e Free Pascal esempio:
Functional languagesEdit
Genericità in HaskellEdit
Il meccanismo di classe tipo di Haskell supporta la programmazione generica.Sei delle classi di tipi predefinite in Haskell (incluso Eq, i tipi che possono essere confrontati per l’uguaglianza e Show, i tipi i cui valori possono essere resi come stringhe) hanno la proprietà speciale di supportare istanze derivate., Ciò significa che un programmatore che definisce un nuovo tipo può affermare che questo tipo deve essere un’istanza di una di queste classi di tipi speciali, senza fornire implementazioni dei metodi di classe come di solito è necessario quando si dichiarano istanze di classe. Tutti i metodi necessari saranno “derivati” – cioè costruiti automaticamente-in base alla struttura del tipo.,Ad esempio, la seguente dichiarazione di un tipo di alberi binari afferma che deve essere un’istanza delle classi Eq e Show:
data BinTree a = Leaf a | Node (BinTree a) a (BinTree a) deriving (Eq, Show)
Ciò si traduce in una funzione di uguaglianza (==) e una funzione di rappresentazione stringa (show) che viene definita automaticamente per qualsiasi tipo di forma BinTree T a condizione che T stessa supporti tali operazioni.,
Il supporto per le istanze derivate di Eq e Show rende i loro metodi == e mostrano generici in un modo qualitativamente diverso dalle funzioni polimorfiche para-metriche: queste “funzioni” (più precisamente, famiglie di funzioni indicizzate per tipo) possono essere applicate a valori di vario tipo, e sebbene si comportino in modo diverso per ogni tipo di argomento, è necessario poco lavoro per aggiungere Ralf Hinze (2004) ha dimostrato che un effetto simile può essere ottenuto per classi di tipi definite dall’utente con determinate tecniche di programmazione., Altri ricercatori hanno proposto approcci a questo e ad altri tipi di genericità nel contesto di Haskell ed estensioni di Haskell (discusso di seguito).
PolyPEdit
PolyP è stata la prima estensione generica del linguaggio di programmazione di Haskell. In PolyP, le funzioni generiche sono chiamate politipiche. Il linguaggio introduce un costrutto speciale in cui tali funzioni politipiche possono essere definite tramite induzione strutturale sulla struttura del functor pattern di un tipo di dati regolare. I tipi di dati regolari in PolyP sono un sottoinsieme di tipi di dati Haskell., Un tipo di dati regolare t deve essere di tipo*→*, e se a è l’argomento di tipo formale nella definizione, tutte le chiamate ricorsive a t devono avere la forma t a. Queste restrizioni escludono tipi di dati più affini e tipi di dati nidificati, dove le chiamate ricorsive sono di una forma diversa.La funzione flatten in PolyP è qui fornita come esempio:
HaskellEdit generico
Haskell generico è un’altra estensione di Haskell, sviluppata presso l’Università di Utrecht nei Paesi Bassi., Le estensioni fornite sono:
- I valori indicizzati al tipo sono definiti come un valore indicizzato sui vari costruttori di tipi Haskell (unità, tipi primitivi, somme, prodotti e costruttori di tipi definiti dall’utente). Inoltre, possiamo anche specificare il comportamento di un valore indicizzato per un costruttore specifico utilizzando i casi del costruttore e riutilizzare una definizione generica in un’altra utilizzando i casi predefiniti.
Il valore risultante indicizzato al tipo può essere specializzato per qualsiasi tipo.
- I tipi indicizzati sono tipi indicizzati su tipi, definiti dando un caso sia per * che per k → k’., Le istanze vengono ottenute applicando il tipo indicizzato a un tipo.
- Le definizioni generiche possono essere utilizzate applicandole a un tipo o tipo. Questo è chiamato applicazione generica. Il risultato è un tipo o un valore, a seconda del tipo di definizione generica applicata.
- L’astrazione generica consente di definire definizioni generiche astraendo un parametro di tipo (di un determinato tipo).
- I tipi indicizzati sono tipi indicizzati sui costruttori di tipi. Questi possono essere usati per dare tipi a valori generici più coinvolti., I tipi indicizzati di tipo risultanti possono essere specializzati per qualsiasi tipo.
Ad esempio, la funzione di uguaglianza in Haskell generico:
CleanEdit
Clean offre PolyP basato sulla programmazione generica e Haskell generico come supportato dal GHC>=6.0. Parametrizza per tipo come quelli ma offre sovraccarico.
Altre linguemodifica
La famiglia di linguaggi di programmazione ML supporta la programmazione generica attraverso il polimorfismo parametrico e moduli generici chiamati funtori.,Sia ML standard che OCaml forniscono funtori, che sono simili ai modelli di classe e ai pacchetti generici di Ada. Le astrazioni sintattiche Scheme hanno anche una connessione con la genericità-queste sono in realtà un superset di templating à la C++.
Un modulo Verilog può prendere uno o più parametri, a cui vengono assegnati i loro valori effettivi all’istanziazione del modulo. Un esempio è un array di registro generico in cui la larghezza dell’array viene fornita tramite un parametro., Tale array, combinato con un vettore di filo generico, può creare un buffer generico o un modulo di memoria con una larghezza di bit arbitraria da un’implementazione di un singolo modulo.
VHDL, essendo derivato da Ada, ha anche funzionalità generiche.
Lascia un commento