Nota: ho già cercato here e non penso che la risposta sia corretta.Istanza implicita dei modelli di funzione quando si prende il proprio indirizzo
Quali sono le regole che regolano l'istanziazione implicita delle funzioni quando si prendono i loro indirizzi? 14.7.1/9 di n3242 dice questo:
Un'implementazione non deve implicitamente un'istanza di un modello di funzione, un modello di elemento, una funzione di membro non virtuale, una classe membro, o un membro di dati statici di un modello di classe ciò non richiede istanziazione.
Ora, non è certamente necessario avere una definizione di funzione per prendere il suo indirizzo. Possiamo prendere l'indirizzo delle funzioni dichiarate in avanti e averle definite in una diversa unità di traduzione.
Stando così le cose, non so quando sarebbe necessario. Tuttavia, i compilatori sembrano avere una propria idea. Test su GCC e VC, ecco alcuni esempi:
template <typename T> void CallBanana() { T::Banana(); }
template <typename T> void CallUnimpl();
template <typename T>
struct S {
static void CallBanana() { T::Banana(); }
static void CallOrange() { T::Orange(); }
static void CallUnimpl();
};
struct B { static void Banana() {} };
int main() {
(void)(&CallBanana<void>); // 1
(void)(&CallUnimpl<void>); // 2
(void)(&S<void>::CallBanana); // 3
(void)(&S<void>::CallOrange); // 4
(void)(&S<void>::CallUnimpl); // 5
(void)(&S<B>::CallBanana); // 6
}
Questi dovrebbero essere commentate in uno alla volta per vedere gli effetti.
GCC 4.7 tested here si lamenterà di 1, 3 e 4. Quindi crea un'istanza di tutte le definizioni se esistono.
VC 2010 (nessun test on-line, sorry) un'istanza di 3 e 4, ma non istanziare 1.
Clang 3.0 tested here ha lo stesso comportamento di VC 2010.
No compilatore si lamenta circa 2 o 5, che mi aspetterei. Mi aspetterei che non riesca a collegare se ho effettivamente usato quei puntatori però.
Su tutti i compilatori, 6 compila. Mi aspetto questo, ma è inteso a dimostrare che l'intero modello di classe non è istanziato (come sostenuto nella risposta a quell'altra domanda) solo perché prendo l'indirizzo di una singola funzione. Se l'intero modello è stato istanziato, allora S :: CallOrange non dovrebbe essere compilato, perché B non contiene una funzione arancione.
Quindi mi chiedo se qualcuno ha una risposta definitiva su quale dovrebbe essere il comportamento corretto. Lo standard sembra affermare che nessuna funzione debba essere istanziata, tuttavia tre popolari compilatori istanziano in alcuni casi, ma differiscono l'uno dall'altro.
Non sono affatto d'accordo, per quanto posso vedere lo standard richiede che la funzione venga istanziata quando viene preso il suo indirizzo e vengono presi tutti e 6 gli indirizzi. Se la funzione non può essere istanziata (1, 3 e 4), verrà generato un errore di compilazione. Quindi direi che 2, 5 e 6 dovrebbero essere istanziati; e dal momento che il loro indirizzo è preso (se lanci a 'void' è irrilevante) la loro assenza dovrebbe provocare un errore del linker (se non ottimizzato). –
"per quanto posso vedere" - dove? Sezione e paragrafo, per favore. I lanci a vuoto sono semplicemente per evitare avvisi su espressioni usate come affermazioni, non correlate a ciò che sto facendo. – Fuz
Se avessi la sezione e il paragrafo, sarebbe una risposta;) Credo che rientri nel caso odr-used. –