2012-01-15 10 views
10

Questo funziona:è un array statico in un intervallo diretto?

int[] a = [ 1, 2, 3, 4 ]; 
fill(a, 5); 

ma questo non lo fa:

int[4] a = [ 1, 2, 3, 4 ]; 
fill(a, 5); 

ed ottengo questo errore:

Error: template std.algorithm.fill(Range,Value) if (isForwardRange!(Range) && is(typeof(range.front = filler))) does not match any function template declaration

invece, devo fare questo in modo che esso per lavorare con array statici:

int[4] a = [ 1, 2, 3, 4 ]; 
fill(a[], 5); 

qualcuno potrebbe spiegare questo comportamento per favore?

risposta

7

No. isForwardRange è false per gli array statici, perché non sono intervalli di inoltro validi. Devono avere uno front valido, empty e popFront.

Un intervallo deve essere modificato mentre è iterato. popFront rimuove il primo elemento dall'intervallo, riducendo la lunghezza dell'intervallo di uno. gli array statici non possono essere modificati. Gli elementi possono essere, ma non possono essere.

int[5] a; 
a.length = 4; 

è illegale. Pertanto, popFront non può funzionare con gli array statici e pertanto gli array statici non possono essere intervalli.

front, empty, e popFront sono dichiarati per gli array in std.array, e front e empty lavorerà con gli array statici, perché prendono esplicitamente array dinamici (non catene), e le matrici statiche possono essere implicitamente convertito in array dinamici quando una funzione assume una matrice dinamica (viene presa una porzione della matrice statica). Tuttavia, popFront non funzionerà, perché richiede uno ref di un array dinamico. E come ho fatto notare, non è possibile fare in modo che popFront funzioni con gli array statici indipendentemente dall'implementazione di popFront, perché non è possibile mutare una matrice statica come sarebbe necessaria per un intervallo.

Ora come per fill, richiede un intervallo in avanti, non un array. Quindi, IFTI (istanza del modello di funzione implicita) proverà ad utilizzare il tipo di array statico (non il tipo di array dinamico) con esso. E poiché isForwardRange è false per un array statico, fill non riesce a compilare con un array statico. Tuttavia, quando si suddivide l'array statico, si passa quindi a un array dinamico, per il quale isForwardRangeètrue. Quindi, funziona.E poiché la slice punta agli stessi elementi e fill muta gli elementi e non la matrice, gli elementi nella matrice statica vengono modificati da fill.

Diffidare, tuttavia, di passare fette di array statici alle funzioni. Finché esiste la matrice statica, va bene. Ma una volta che l'array statico lascia l'ambito, qualsiasi porzione di esso non è valida. Quindi, facendo qualcosa come

int[] foo() 
{ 
    int[5] a = [1, 2, 3, 4, 5] 
    return find(a[], 3); 
} 

sarebbe molto male. Un riferimento a a sta sfuggendo a foo - ovvero una porzione dei suoi ultimi 3 elementi.

Quindi, se si passa una porzione di una matrice statica a una funzione, è necessario assicurarsi che non vi siano riferimenti a tale matrice. fill, tuttavia, dovrebbe andare bene.

+0

Ho ragione nel dire che devi tagliare anche con 'Array' e' SList'? Sembra un po 'un difetto di progettazione. –

+0

Non è proprio un difetto di progettazione IMHO. È più che mai un caso che gli array dinamici siano uno strano caso speciale di gamme. Ma dal momento che sono il caso più comune, è quello a cui siamo abituati. Un container dovrebbe convertirsi implicitamente al suo tipo di slice per IFTI in modo che non debba essere esplicitamente tagliato quando passa ad una funzione, e che renderebbe molto più difficile passare contenitori a funzioni basate su modelli. E non sono sicuro che sarebbe una buona idea che tutti i tipi affettabili fossero automaticamente affettati con IFTI in generale - anche quando si tratta solo di intervalli. –

+0

Puoi pensare in questo modo. I contenitori, inclusi gli array statici, devono essere tagliati per ottenere un intervallo su di essi. Quindi, se si desidera un intervallo su di essi per qualsiasi motivo, incluso il passaggio a una funzione basata sull'intervallo, è necessario suddividerli esplicitamente. Ma gli array dinamici sono intervalli _already_ anziché contenitori, quindi non è necessario eseguire il slicing. –

7

isForwardRange verifica l'esistenza del front, empty proprietà e popfront() funzione

Il problema è che popfront() avrebbe bisogno di ridurre la matrice, come si (dovrebbe) sapere che si può non ridimensionare un array statico, ma un fetta di un array statico (essenzialmente un array dinamico normale) può essere ridimensionato (questo naturalmente non influenza la matrice statica)

chiarire a.popfront() avrebbe bisogno di trasformare una da int[4] a int[3] ma non è possibile

+0

i.e. L'argomento e i tipi di ritorno di popfront devono essere uguali? – BCS

+0

'popfront' è una funzione che modifica il parametro' this' in modo che la proprietà 'front' cambi (puntando all'elemento 'next') (e forse la proprietà' empty') questo non sia possibile con l'array statico perché il la lunghezza è impostata in fase di compilazione e parte del tipo. –

Problemi correlati