2010-08-12 19 views
6

in C++ è ok per avere un funcction che prende una funzione di tipo locale:Perché i modelli non possono utilizzare i tipi locali?

int main() { 
    struct S { static void M(const S& s) { } }; 
    S s; 
    S::M(s); 
} 

ma non OK per avere un modello che fa:

template<typename T> void Foo(const T& t) { } 

int main() { 
    struct S { } s; 
    Foo(s); // Line 5: error: no matching function for call to 'Foo(main()::S&)' 
} 

14.3.1 paragraph 2 in the c++ standard.

Un tipo senza collegamento [...] non deve essere usato come argomento modello per un parametro tipo di modello

Perché C++ non lo consente?


La migliore spiegazione che ho sentito finora è che i tipi di interni non hanno alcun legame e che questo potrebbe implicare che una funzione che li prende come un ARG deve avere alcun legame. Ma non c'è motivo per cui possa vedere che un modello di istanziazione deve avere un collegamento.


p.s. Si prega di non dire semplicemente "thats not allowed because the standard says it's not"

+5

Non c'è una buona ragione, e C++ 0x rimuoverà questa restrizione (ma non quella collegata in p.s .; non ho ancora idea del perché non sia permesso). –

+0

@Mike; Breve e dritto al punto! – BCS

risposta

3

Suppongo che sia perché richiederebbe che il modello sia istanziato efficacemente nell'ambito della funzione, poiché è lì che tali tipi sono visibili. Tuttavia, allo stesso tempo, le istanze dei template dovrebbero agire come se fossero nello scope in cui è definito il modello. Sono sicuro che è possibile affrontarlo in qualche modo, ma se ho ragione, il corpo degli standard ha deciso di non attribuire tale peso agli scrittori di compilatori.

Una decisione simile era il motivo vector<vector<int>> sintassi non valida per lo standard; rilevando che la costruzione richiede una certa interazione tra il compilatore e le fasi del parser. Tuttavia, questo sta cambiando, perché gli standard degli standard C++ 0x hanno rilevato che tutti i compilatori lo stanno rilevando comunque per emettere messaggi di errore sensati.

Sospetto che se fosse dimostrato che consentire l'implementazione di questa costruzione era semplice e che non introduceva alcuna ambiguità nelle regole di ambito linguistico, si potrebbe vedere un giorno lo standard modificato anche qui.

+1

"Someday" sarà non appena C++ 0x sarà ratificato, a meno che non cambino idea. La bozza finale rimuove questa restrizione. –

+0

Potrei immaginare un'architettura di compilatore in cui sarebbe difficile da implementare, ma posso anche pensare a quelli in cui si sarebbe avuto gratuitamente. – BCS

7

Credo che la difficoltà prevista era con due istanze di Foo<T> che in realtà significava cose completamente diverse, perché T non era lo stesso per entrambi. Parecchie implementazioni iniziali di template (incluso cfront) hanno usato un repository di istanze di template, così il compilatore può istanziare automaticamente un template su un tipo richiesto quando/se si è scoperto che un'istanza su quel tipo non era già nel repository.

Per fare in modo che funzioni con tipi locali, il repository non sarebbe solo in grado di memorizzare il tipo su cui il modello è stato istanziato, ma invece dovrebbe fare qualcosa come la creazione di un "percorso" completo per il tipo per l'istanziazione. Anche se questo è probabilmente possibile, penso che sia stato visto come un sacco di lavoro extra per il piccolo (se del caso) reale beneficio.

Da allora, le regole sono cambiate abbastanza che il compilatore è già tenuto a fare qualcosa che si tratta solo di equivalente, trovare (e coalescenza) istanze nello stesso tipo in luoghi diversi (compresa tutta TU), in modo che due istanze di foo<int> (per esempio) non violare l'ODR.Sulla base di tale realizzazione, la restrizione è stata allentata in (la bozza attuale di) C++ 0x (non è ancora possibile creare un'istanza di una classe template su un tipo locale, ma è possibile utilizzare un tipo locale come parametro per una funzione template) .

+0

In breve, era più lavoro per il compilatore? – BCS

+0

@BCS: Anche se questo è probabilmente vero, non è * tanto * che è stato più lavoro per il compilatore, dato che è 1) la maggior parte del lavoro extra viene ora fatto per altri motivi, e 2) compilare C++ è ora così complesso che le persone sono più disposte ad accettare aggiungendo ancora più complessità, a patto che non sia troppo drastico. –

+0

§14.3.1 [temp.arg.type] ha diversi esempi di passaggio di tipi locali a un modello di classe. – Potatoswatter

Problemi correlati