2013-05-13 10 views
10

In 5.1.1/3 di C++ norma [expr.prim.general]`* questo` al di fuori del corpo della funzione membro?

Diversamente l'espressione oggetto in altri contesti, * questo non è necessario che sia di tipo completo per scopi di accesso membro della classe esterni il corpo della funzione membro. Solo i membri della classe dichiarati prima alla dichiarazione sono visibili.

E poi questo esempio:

struct A { 
    char g(); 
    template<class T> auto f(T t) -> decltype(t + g()) 
    { return t + g(); } 
}; 
template auto A::f(int t) -> decltype(t + g()); 

Può spiegare la citazione e l'esempio? Cosa viene dimostrato esattamente qui?

+1

Credo si riferisce all'utilizzo di 'A :: G' nella firma di 'f' invece del suo corpo. Complifica le cose per gli scrittori di compilatori, perché ti viene chiesto di (potenzialmente) eseguire una risoluzione di sovraccarico su 'g()', prendendo in considerazione 'A :: g', anche se' A' non è completamente definito. Prima di questo, una cosa tipica era analizzare prima tutte le dichiarazioni (di metodi e membri) e quindi usare un "A" completamente definito per analizzare i corpi dei metodi. –

+0

@MatthieuM .: Notare che è esterno al corpo della funzione. È comunque necessario rimandare l'analisi dei corpi delle funzioni in linea fino a dopo aver analizzato un identificatore di classe. –

risposta

4

significa che è possibile accedere ai membri tramite this, esplicitamente o implicitamente, corpi di funzione al di fuori all'interno di una definizione di classe. A quel punto, il tipo è incompleto e in genere non è possibile accedere ai membri di tipi incompleti.

Ma si può farlo solo entro ristretti parti di una dichiarazione di funzione membro; la frase precedente dice di this:

Non deve comparire davanti al opzionale cv-qualificatore-ss

il che significa che non è possibile utilizzare in un parametro o leader specifica tipo di ritorno. Per quanto posso vedere, l'unico posto in cui puoi usarlo, al di fuori del corpo di una funzione, è in un tipo di ritorno finale.

Potrebbe essere necessario eseguire questa operazione quando si utilizza decltype in un tipo di ritorno finale, per ottenere il tipo di un'espressione che coinvolge un membro non statico. L'esempio lo dimostra utilizzando implicitamente this per accedere a g() nel tipo di ritorno finale. Sarebbe stato più chiaro ciò che veniva dimostrato se fosse stato scritto come decltype(t + this->g()).

+0

È l'unica applicazione? 'decltype' in un' trailing-return-type'? (o credo anche in una dichiarazione di parametro) –

+0

@ user1131467: non lo so. È l'unico che posso immediatamente pensare, ma non sono molto fantasioso il lunedì. –

+0

@ user1131467: non necessariamente nel tipo di ritorno finale. Si potrebbe usare 'decltype (this)' anche quando il tipo di ritorno non è trailing, o in una dichiarazione di parametro –

6

Che cosa è esattamente questo un esempio di? Quale affermazione è stata dimostrata qui?

sia dimostrata L'affermazione è che:

Diversamente l'espressione oggetto in altri contesti, * questo non è necessario che sia di tipo completo per scopi di accesso membro della classe (5.2.5) fuori il corpo della funzione membro.

di fuori del corpo della funzione membro v'è una chiamata a g(), che significa this->g(). Qui, il tipo di *this (ad esempio A) non è completo.

Per paragrafo 9.2/2 del C++ 11 standard:

Una classe è considerato un tipo completamente definito oggetto (3,9) (o tipo completo) alla chiusura } del classe- specificatore. All'interno della classe specifica membro, la classe è considerata completa all'interno dei corpi delle funzioni, argomenti predefiniti e inizializzatori brace-or-equal-per membri di dati non statici (inclusi tali elementi nelle classi nidificate ). Altrimenti è considerato incompleto all'interno della sua classe specifica membro.

+0

Sì e il 'trailing-return-type' non è in quella lista. –

+0

@ user1131467: Esatto, quindi è incompleto quando si esegue 'this-> g()' –

2

Prima di tutto, tutte le espressioni di accesso utente vengono trasformati dal compilatore:

struct X{ 
    int a; 
    void f(){} 
    void g(int b){ 
    int x = a + b; // actually: int x = (*this).a + b 
    f(); // actually: (*this).f(); 
    } 
}; 

§9.3.1 [class.mfct.non-static] p3

[...] il id-espressione si trasforma in un accesso membro della classe espressione (5.2.5) utilizzando (*this) (9.3.2) come espressione di postfix a sinistra dell'operatore .. [...]

Ora, l'esempio dello standard chiama una funzione membro al di fuori del corpo di un'altra funzione membro, nel tipo trailing-return. E che la chiamata si trasforma troppo:

template<class T> auto f(T t) -> decltype(t + (*this).g()) 
{ return t + (*this).g(); } 

e al di fuori di un corpo funzione membro, *this è ovviamente un tipo incompleto. Ciò significa che è possibile accedere solo i nomi che sono stati dichiarati prima dell'uso - ma quella parte non si applica solo alla *this utilizzo:

struct X{ 
    using typeA = int; 
    typeA f(); // OK, 'typeA' has been declared before 

    typeB g(); // Error: 'typeB' not declared before usage 
    using typeB = float; 
}; 
+0

Penso che sia incompleto nella definizione in linea di 'A :: f' all'interno dello specificatore di classe, tuttavia penso che sia completo nella dichiarazione di' A :: f' che segue la parentesi di chiusura. –

+0

All'interno del corpo di una definizione di funzione membro, '* this' è sempre considerato un tipo completo, vedere' §9.2/2'. – Xeo

+0

Sì, ma il tipo di ritorno finale non fa parte del corpo della funzione. –

Problemi correlati