2013-05-21 8 views
9

Ho ottenuto l'errore di compilazione sotto il codice.decltype come un tipo di ritorno nella funzione membro della classe

struct B{ 
    double operator()(){ 
     return 1.0; 
    } 
}; 

struct A { 
    auto func() -> decltype(b()) 
    { 
     return b(); 
    } 

    B b; 
}; 

Tuttavia, se riorganizzare il A, si compila.

gcc 4.8 ha dichiarato che "b" non è stato dichiarato in questo ambito.

struct A { 
    B b; 
    auto func() -> decltype(b()) 
    { 
     return b(); 
    } 
}; 

Quindi, cosa c'è di sbagliato con il primo ??

+0

Si prega di essere più specifico in quello che stai cercando di chiedere. "È valido?" potrebbe essere un po 'vago per la comunità per comprendere appieno ciò che stai chiedendo. –

+0

@JeffWolski: Sì, sono d'accordo, quindi ho modificato la dicitura :) – Sungmin

risposta

8

La definizione di class viene elaborata in due passaggi: prima vengono raccolte le dichiarazioni membro, compresa la funzione firme, quindi vengono analizzati i corpi delle definizioni.

Il corpo della funzione ha quindi accesso a tutte le dichiarazioni membro, comprese quelle successive, ma il prototipo della funzione vede solo le dichiarazioni precedenti.

+0

Il tipo di ritorno in ritardo non fa parte del corpo/definizione. Per esempio. può apparire solo in una dichiarazione. –

+0

Sì. Usando 'auto ... ->' sposta sintatticamente il tipo di ritorno, e ti permette di usare i nomi dei parametri nel tipo di ritorno, ma questa è l'unica differenza. – Potatoswatter

9

È valido?

L'ultimo esempio è ben formato, mentre il primo non lo è (quindi GCC è corretto).

Paragrafo 3.4.1/7 sulla ricerca del nome qualificato specifica:

Un nome utilizzato nella definizione di una classe Xall'esterno di un corpo funzione membro, argomento standard, brace-o- pari-inizializzatore di un membro di dati non statico o una classe annidata definizione sarà dichiarato in uno dei seguenti modi :

-prima del suo utilizzo in classe X o essere un membro di una classe di base di X (10.2), o

- [...]

E quanto segue sono altre condizioni che non si applicano a il tuo caso.

1

Si può anche farlo funzionare in questo modo:

struct B 
{ 
    double operator()() 
    { 
     return 1.0; 
    } 
}; 

// my implementation does not have std::declval 
template < typename T > T&& declval(); 

struct A 
{ 
    B b; 
    auto func() -> decltype(declval<B>().operator()()) 
    { 
     return b(); 
    } 
}; 

edit: o dal B è portata già comunque senza bisogno di auto, -> decltype e declval

struct A 
{ 
    B b; 
    decltype(Q()()) func() 
    { 
     return b(); 
    } 
}; 
+0

Grazie, è esattamente quello che volevo fare. Non sapevo di declval. Tuttavia, non era la risposta diretta per la mia domanda. Quindi ne ho scelto un altro. Mi aiuta molto:) – Sungmin

Problemi correlati