2015-08-19 12 views
34

अंक बनाम: (एक टेम्पलेट कार्य करने के लिए) एक सामान्य लैम्ब्डा गुजर कि this कब्जा और एक स्पष्ट this-> बिना this के एक सदस्य फ़ंक्शन को कॉल करने पर संकलन नहीं है जीसीसी। यदि लैम्ब्डा सामान्य नहीं है, या यदि लैम्ब्डा किसी भी अन्य समारोह में नहीं भेजा जाता है लेकिन जगह में बुलाया जाता है, तो यह एक स्पष्ट this-> के साथ संकलित करता है। Clang सभी परिस्थितियों में कोड के साथ शांत है।कॉलिंग `सामान्य लैम्ब्डा से this` सदस्य समारोह - बजना जीसीसी

क्लैंग बनाम जीसीसी के दूसरे दौर के लिए समय। कौन सही है

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; 
} 

  • bar() = call([this](auto x){ foo(x); });
    • बजना ++ 3.6+ साथ संकलित करता है।
    • जी ++ 5.2+ संकलित नहीं करता है।

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


  • bar() = call([this](auto x){ this->foo(x); });
    • बजना ++ 3.6+ साथ संकलित करता है।
    • जी ++ 5.2+ संकलन।

  • bar() = call([this](int x){ foo(x); });
    • बजना ++ 3.6+ साथ संकलित करता है।
    • जी ++ 5.2+ संकलन।

  • bar() = [this](auto x){ foo(x); }(1);
    • बजना ++ 3.6+ साथ संकलित करता है।
    • जी ++ 5.2+ संकलन।

this-> आवश्यक केवल एक सामान्य लैम्ब्डा के मामले में क्यों है?

this-> क्यों आवश्यक नहीं है यदि लैम्ब्डा call पर पास नहीं किया गया है?

गैर मानक-अनुपालन कौन है?

+3

आपके द्वारा नोट किए गए विसंगतियों से संकेत मिलता है कि क्लैंग यहां सही है। –

+7

मानक को देखे बिना, मैं पूर्ण निश्चितता के साथ कह सकता हूं कि क्लैंग सही है। भले ही यह मानक से असहमत हो, फिर भी यह सही है; उस मामले में मानक गलत है। जीसीसी का व्यवहार पूरी तरह से कोई समझ नहीं आता है। –

+2

[संबंधित लेकिन डुप्ली नहीं?] (Http://stackoverflow.com/q/20312062/819272) – TemplateRex

उत्तर

12

यह एक जीसीसी बग है। [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 ]

अपने उदाहरण में जब से तुम this पर कब्जा, नाम देखने Example के वर्ग के सदस्यों, जो इसलिए Example::foo खोजना चाहिए शामिल करना चाहिए। यदि foo(x)लैम्ब्डा अभिव्यक्ति के संदर्भ में छपी देखने प्रदर्शन क्या होगा के समान है, कि अगर कोड की तरह दिखाई देता है:

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

कम से कम इस बग एक बहुत ही सरल तरीके को है के रूप में इंगित प्रश्न में: बस this->foo(x); करें।

+0

क्या यह ट्रैक करने के लिए एक अपस्ट्रीम बग रिपोर्ट है? – jotik

+0

@ जॉटिक हाँ, ओपी [इसकी सूचना दी] (http://stackoverflow.com/questions/32097759/calling-this-member-function-from-generic-lambda-clang-vs-gcc/32098850#comment52090459_32097759)। – Barry

+1

ने कहा कि बग यहां ट्रैक किया गया है: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67274 –

संबंधित मुद्दे