2015-07-03 10 views
25

Der Versuch, diese einfache Klasse zu kompilieren:Warum sieht declltype die Member-Deklaration nicht?

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

führt zu einem Fehler:

$ 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()) 
          ~~~~^

Warum decltype sehen nicht die Klasse Mitglied?

+0

in der Zwischenzeit eine Abhilfe, die ich gefunden: die Membervariable vor der deklarieren 'declype' verwenden. Aber kann jemand den Standard zitieren, der dieses Verhalten vorschreibt? Oder ist es einfach für Compilerschreiber? – Bulletmagnet

+1

Duplikat von http://stackoverflow.com/q/12362888/866732? – WiSaGaN

+0

Ich glaube nicht, dass das ein Duplikat ist, das Mitglied wird über der Funktion dort deklariert. – TartanLlama

Antwort

22

Von 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...

Da der hinteren Rückgabetyp Teil ist die Funktion Deklaration eher als die Definition, kann es nicht vorausschauen, um zu sehen, was sonst in der Klasse deklariert ist, also müssen Sie dieses Mitglied über der Funktionsdeklaration deklarieren.

2

die Deklaration des Elements bewegen, bevor die Funktion wie folgt:

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


}; 
16

Wenn C++ 14 verfügbar ist, können Sie den Hinterrückgabetyp weglassen, also außerhalb Funktionskörpern Referenzierung ein Elements zu vermeiden und auch was der Code kompakte:

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

Im Allgemeinen ist es richtiger zu verwenden decltype(auto) für eine solche Weiterleitungsmethoden, Rückkehr so ​​Typ kann ein Hinweis sein, obwohl in diesem Fall ist es die gleichen (dank @Nawaz):

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

Leider haben wir schon Glück, dass wir C++ 11 (das einzige Projekt in meiner Firma) benutzen können, also muss ich mit TartanLlama gehen :) – Bulletmagnet

+0

Ich denke es sollte 'declltype (auto)' sein, obwohl in diesem Fall 'auto' funktionieren würde. – Nawaz

+1

@Nawaz Danke, dass du darauf hingewiesen hast, ich habe die Antwort aktualisiert. –

Verwandte Themen