2016-03-12 2 views
5

Ich verwende Assertion-Makro von assert.h Ich habe definiert Lambda Assertion Überprüfung durchführen.Erhalten zu viele Argumente, um function-like Makroaufruf Kompilierungsfehler beim Definieren von Lambda innerhalb Assert (assert.h) in Xcode [C++]

int val1 = 0; 
int val2 = 1; 

const auto check = [val1,val2]()-> bool 
{ 
    return val1 < val2; 
}; 
// no error for this call 
assert(check() && "Test is failed"); 

// no error for this call 
assert([=]()-> bool 
     { 
      return val1 < val2; 
     }() && "Test is failed"); 
//compile error for this call "too many arguments provided to function-like macro invocation" 
assert([val1,val2]()-> bool 
     { 
      return val1 < val2; 
     }() && "Test is failed"); 

warum ich

zu viele Argumente zur Verfügung gestellt bekommen für den Fall funktionieren ähnliche Makroaufruf

Kompilierungsfehler, wenn ich behaupte, bin mit Makro und definieren Lambda mit mehr als einem Argument in der Aufnahmeliste?

Antwort

5

Das Problem ist das Komma in der Erfassungsliste.

Der Präprozessor hat ein extrem begrenztes Verständnis der C++ - Syntax, es macht hauptsächlich triviale Textersetzung. Wenn ein Komma nicht zwischen übereinstimmenden inneren Klammern steht (und natürlich nicht Teil eines Tokens wie ein String-Literal), behandelt der Präprozessor es als Trennzeichen für Argumente des Makroaufrufs.

So denkt der Präprozessor, dass Sie Assert mit den beiden Argumenten [this und den Rest des Materials hinter dem ersten Komma aufrufen, was den Fehler ergibt.

Sie diesen Fehler, indem Sie einen zusätzlichen Satz von Klammern beheben:

int i = -7, j = 7; 
assert(([i,j](){return i + j;}())); 

Für die Standard-Liebhaber:

Die Reihenfolge der Vorverarbeitung von außen am weitesten passenden begrenzt Token Klammern bilden die Liste der Argumente für das funktionsähnliche Makro. Die einzelnen Argumente in der Liste werden durch Komma Vorverarbeitungstoken getrennt, aber Kommavorverarbeitungstoken zwischen übereinstimmenden inneren Klammern trennen keine Argumente. Wenn Sequenzen von Vorverarbeitungstoken in der Liste der Argumente enthalten sind, die andernfalls als Vorverarbeitungsdirektiven fungieren würden, 155 ist das Verhalten nicht definiert.

16.3/11 in N4140, Schwerpunkt meiner.

+0

Baum mit Augen noch eine Sache nicht klar, das Argument der Behauptung insert.h ist innen() '#define \t assert (e) \ (__builtin_expect (! (E), 0)? __assert_rtn (__ func__, __FILE__, __LINE__, #e): (void) 0) ' –

+1

@TM Diese Parens kommen zu spät, für das Zitat oben sind die Parens und Kommas * vor * der Erweiterung relevant, nicht die im Ergebnis. –

2

Der Präprozessor ist sehr einfach, er sieht alle Kommas als Argumenttrennzeichen.

Sie können also kein Makro verwenden, wenn Sie irgendetwas mit einem Komma als Argument für das Makro übergeben.

+0

Joachim Pileborg, warum es kompiliert Fehler für andere Kommas im Falle des Anrufs mit [=] nicht wirft? –

+0

@TM Um ehrlich zu sein, glaube ich nicht, dass du uns die Wahrheit sagst. Der Präprozessor hat kein Konzept oder keine Kenntnis des tatsächlichen C++ - Codes oder der C++ - Syntax, der Präprozessor kennt nur seine eigene begrenzte Sprache, wobei alle Kommas in einem Makro- "Aufruf" als Argumenttrennzeichen verwendet werden. Daher glaube ich nicht, dass Code funktioniert und Ihnen keinen Fehler gibt. –

+0

Joachim Pileborg aber es funktioniert :) ohne Kompilierfehler Ich benutze Xcode Version 7.2.1 (7C1002) –

Verwandte Themen