2015-08-19 13 views
34

Issue: eine generische Lambda (auf eine Template-Funktion), die die this und ruft eine Memberfunktion von this ohne explizite this-> fängt nicht kompilieren gcc. Wenn das Lambda nicht generisch ist oder wenn das Lambda nicht an eine andere Funktion übergeben, sondern an Ort und Stelle aufgerufen wird, kompiliert es sich mit einem expliziten this->. Clang ist cool mit dem Code in allen Situationen.Aufruf `this` Memberfunktion von generic Lambda - Klirren vs gcc

Zeit für eine weitere Runde von clang vs gcc. Wer hat Recht?

Wandbox example


template<typename TF> 
void call(TF&& f) 
{ 
    f(1); 
} 

struct Example 
{   
    void foo(int){ } 

    void bar() 
    { 
     call([this](auto x){ foo(x); }); 
    } 
}; 

int main() 
{ 
    Example{}.bar(); 
    return 0; 
} 

  • Mit bar() = call([this](auto x){ foo(x); });
    • Klirren ++ 3.6+ kompiliert.
    • g ++ 5.2+ wird nicht kompiliert.

      error: cannot call member function 'void Example::foo(int)' without object call([this](auto x){ foo(x); });`


  • Mit bar() = call([this](auto x){ this->foo(x); });
    • Klirren ++ 3.6+ kompiliert.
    • g ++ 5.2+ kompiliert.

  • Mit bar() = call([this](int x){ foo(x); });
    • Klirren ++ 3.6+ kompiliert.
    • g ++ 5.2+ kompiliert.

  • Mit bar() = [this](auto x){ foo(x); }(1);
    • Klirren ++ 3.6+ kompiliert.
    • g ++ 5.2+ kompiliert.

Warum ist die this-> notwendig, nur im Falle einer allgemeinen Lambda?

Warum ist die this-> nicht erforderlich, wenn das Lambda nicht an call übergeben wird?

Wer ist nicht standardkonform?

+3

Die von Ihnen notierten Inkonsistenzen weisen darauf hin, dass der Clang hier korrekt ist. –

+7

Ohne auf den Standard zu schauen, kann ich mit absoluter Sicherheit sagen, dass Clang recht hat. Selbst wenn es nicht mit dem Standard übereinstimmt, ist es immer noch richtig; In diesem Fall ist der Standard falsch. Das Verhalten von GCC macht überhaupt keinen Sinn. –

+2

[verwandt aber nicht ein Betrogener?] (Http://stackoverflow.com/q/20312062/819272) – TemplateRex

Antwort

12

Dies ist ein gcc-Fehler. Von [expr.prim.lambda]:

The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator, but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming id-expressions referring to non-static class members into class member access expressions using (*this) (9.3.1), the compound-statement is considered in the context of the lambda-expression. [ Example:

struct S1 { 
    int x, y; 
    int operator()(int); 
    void f() { 
     [=]()->int { 
      return operator()(this->x + y); 
       // equivalent to S1::operator()(this->x + (*this).y) 
       // this has type S1* 
     }; 
    } 
}; 

—end example ]

Da in Ihrem Beispiel Sie this erfassen, sollte der Name Lookup-Klasse Mitglieder Example umfassen, die daher Example::foo finden sollte. Die Suche durchgeführt ist identisch zu dem, was passieren würde, wenn foo(x) im Rahmen des Lambda-Ausdrucks erschien selbst, das heißt, wenn der Code aussieht:

void bar() 
{ 
    foo(x); // clearly Example::foo(x); 
} 

Wenigstens dieser Fehler hat eine sehr einfache Abhilfe wie angegeben in der Frage: Just do this->foo(x);.

+0

Gibt es einen Upstream-Fehlerbericht, um dies zu verfolgen? – jotik

+0

@jotik Ja, OP [berichtete] (http://stackoverflow.com/questions/32097759/calling-this-member-function-from-generic-lambda-clang-vs-gcc/32098850#comment52090459_32097759). – Barry

+1

Dieser Bug wird hier verfolgt: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67274 –

Verwandte Themen