2015-07-03 23 views
25

Cercando di compilare questo semplice classe:Perché decltype non vede la dichiarazione membro?

#include <vector> 
struct M 
{ 
// interface 
    auto begin() -> decltype(identities.begin()) 
    { 
     return identities.begin(); 
    } 
// implementation 
private: 
    std::vector<int> identities; 
}; 

risultati in un errore:

$ g++-510 where.cpp -std=c++11 
where.cpp:57:35: error: ‘struct M’ has no member named ‘identities’ 
    auto begin() ->decltype(this->identities.begin()) 
           ^
where.cpp:57:35: error: ‘struct M’ has no member named ‘identities’ 

$ clang++ where.cpp -std=c++11 -Wall -pedantic -Wextra 
where.cpp:57:35: error: no member named 'identities' in 'M' 
    auto begin() ->decltype(this->identities.begin()) 
          ~~~~^

perché non decltype vedere il membro della classe?

+0

nel frattempo ho trovato una soluzione: dichiarare la variabile membro prima della uso 'decltype'. Ma qualcuno può citare lo standard che prescrive questo comportamento? O è solo più facile per gli scrittori di compilatori? – Bulletmagnet

+1

Duplicato di http://stackoverflow.com/q/12362888/866732? – WiSaGaN

+0

Non penso che sia un duplicato, il membro è dichiarato sopra la funzione lì. – TartanLlama

risposta

22

Da N3337 [basic.lookup.unqual]/7:

A name used in the definition of a class X outside of a member function body or nested class definition shall be declared in one of the following ways:

  • before its use in class X or be a member of a base class of X, or...

Poiché il tipo di ritorno finale è parte la funzione dichiarazione anziché la definizione, non può guardare avanti per vedere cos'altro è dichiarato nella classe, quindi è necessario dichiarare quel membro sopra la dichiarazione di funzione.

2

Spostare la dichiarazione dell'organo prima della funzione in questo modo:

#include <vector> 
struct M 
{ 
    // implementation 
    private: 
     std::vector<int> identities; 
    public:  
    // interface 
    auto begin() -> decltype(identities.begin()) 
    { 
     return identities.begin(); 
    } 


}; 
16

Se C++ 14 è disponibile, è possibile omettere il tipo di ritorno trascinamento, evitando riferimento dell'utente all'esterno del corpo funzione e anche rendere il codice più compatto:

auto begin() { 
    return identities.begin(); 
} 

In generale è più corretto utilizzare decltype(auto) per tali metodi di inoltro, quindi tipo di ritorno può essere un riferimento, sebbene in questo caso particolare è lo stesso (grazie a @Nawaz):

decltype(auto) begin() { 
    return identities.begin(); 
} 
+0

Ahimè, siamo già fortunati solo per poter usare C++ 11 (l'unico progetto nella mia azienda), quindi dovrò andare con TartanLlama :) – Bulletmagnet

+0

Penso che dovrebbe essere 'decltype (auto)', anche se in questo caso 'auto' funzionerebbe. – Nawaz

+1

@Nawaz grazie per avermelo spiegato, ho aggiornato la risposta. –

Problemi correlati