5 Stimmen

Der Vektor-Konstruktor mit zwei Parametern wird als Funktionsdeklaration geparst

Betrachten Sie dieses Beispiel:

#include 
#include 
#include 
#include 

int main()
{
    std::string sen = "abc def ghi jkl";
    std::istringstream iss(sen);

    std::vector    // declaration in question
    vec(std::istream_iterator(iss),
        std::istream_iterator());

    std::copy(vec.begin(), vec.end(),
              std::ostream_iterator(std::cout, "\n"));
}

Der Compiler wirft einen Fehler beim Aufruf von std::copy

Anforderung nach Element 'begin' in 'vec', der kein Klassentyp ist...

Ich kann den Fehler so umgehen:

std::istream_iterator it_begin(iss);
std::istream_iterator it_end;
std::vector vec(it_begin, it_end);

oder indem ich Klammern um jeden Parameter setze, so wie hier:

std::vector
vec((std::istream_iterator(iss)),
    (std::istream_iterator()));

oder sogar mit der neuen einheitlichen Initialisierung in C++11:

std::vector vec { /*begin*/, /*end*/ };

Warum interpretiert der Compiler die Deklaration im Beispiel als Funktionsdeklaration? Ich kenne die Problematik des "most vexing parse", aber ich dachte, das passiert nur bei leeren Parameterlisten. Ich frage mich auch, warum der zweite Workaround funktioniert.

9voto

Lightness Races in Orbit Punkte 367630

Es ist immer noch die nervigste Analyse.

std::vector                     // Rückgabetyp
vec(                                         // Funktionsname
    std::istream_iterator(iss), // Parameter 1: ein Iterator namens (iss) oder einfach iss
    std::istream_iterator()     // Parameter 2: unbenannte Funktion 
);                                           // die einen Iterator zurückgibt

Geordi sagt:

 << ETYPE_DESC(vec); std::vector vec(std::istream_iterator(iss), std::istream_iterator());
 L-Wert-Funktion, die einen istream_iterator, long> , einen Zeiger auf eine Funktion ohne Parameter, die einen istream_iterator, long> zurückgibt, und einen Vektor von Zeichenfolgen zurückgibt

Im Grunde genommen liegt der Kern darin, dass Ihre Parameterbezeichnungen in Klammern stehen können (d.h. iss(iss)), ohne die Semantik der Deklaration zu ändern. Manchmal.

Verwenden Sie einen weiteren Satz von Klammern die auch den Typ umgeben, wie Sie gezeigt haben, um zu erzwingen, dass der erste Parameter (und folglich auch der zweite) als Ausdruck und nicht als Deklaration analysiert wird.


Wenn es hilft, betrachten Sie auch:

void foo(int (x)) {
   cout << x;
}

int main() {
   foo(42);
}

Die Ausgabe lautet 42.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X