2016-07-12 15 views
37

Si consideri il seguente:Perché la deduzione automatica del tipo di deduzione funziona con tipi non completamente definiti?

template<typename Der> 
struct Base { 
    // NOTE: if I replace the decltype(...) below with auto, code compiles 
    decltype(&Der::operator()) getCallOperator() const { 
     return &Der::operator(); 
    } 
}; 

struct Foo : Base<Foo> { 
    double operator()(int, int) const { 
     return 0.0; 
    } 
}; 

int main() { 
    Foo f; 
    auto callOp = f.getCallOperator(); 
} 

Voglio creare una funzione di membro di classe di base CRTP con un tipo di ritorno a seconda firma del operator() nella classe derivata. Tuttavia, decltype(&Der::operator()) non riesce a compilare; La funzione membro operator() in Foo non è visibile. Presumo che ciò avvenga perché il modello di classe base viene istanziato prima che Foo sia completamente definito.

Sorprendentemente, se inserisco auto per il tipo di reso che compila. Supponevo che il auto facesse sì che il compilatore deducesse il tipo di ritorno dal corpo della funzione e fallisse - perché il corpo utilizza il tipo non completamente definito Foo.

Questo comportamento è lo stesso sia per MSVC 2.015,3 e Clang 3,8

Perché il codice di iniziare a lavorare con auto? La deduzione di tipo auto in qualche modo "posticipa" l'istanza? O utilizzare un contesto diverso rispetto a un'espressione di tipo di ritorno scritto a mano?

+5

Buona domanda. Upvoted. –

+0

Possibile duplicato di [CRTP e C++ 1y tipo di deduzione di ritorno] (http://stackoverflow.com/questions/19892479/crtp-and-c1y-return-type-deduction) – Holt

+0

È lo stesso problema ma l'approccio di domande e risposte da un'angolazione leggermente diversa. Qui abbiamo "come l'auto deduzione è diversa", la domanda collegata e la sua risposta è più su "come posso far funzionare l'espressione scritta a mano". Anche se può ancora qualificarsi come duplicato ... –

risposta

24

L'ipotesi è corretta. Un tipo di rendimento dedotto non viene effettivamente dedotto fino a quando non è necessaria la firma della funzione. Ciò significa che verrà dedotto nel contesto della chiamata a getCallOperator, a cui il punto Foo è completamente definito.

Questo è specificato in 7.1.6.4p12: Tipo

ritorno deduzione per un modello di funzione con un segnaposto nel suo tipo dichiarato si verifica quando la definizione viene creata un'istanza anche se il corpo della funzione contiene un'istruzione di ritorno con un operando non dipendente dal tipo.

Problemi correlati