2017-05-15 20 views
11

मैं एक कोड का टुकड़ा है कि संकलित करता है तथा बजना ++ 4 (और ट्रंक) में ठीक से काम करता लेकिन जी ++ 7 (और ट्रंक) में संकलित करने के लिए विफल रहता है की खोज की है बनाम। के मैं निम्नलिखित struct प्रकार है मान लेते हैं:ओवरलोडिंग structs - जीसीसी बजना

struct a { void foo() { } }; 
struct b { void bar() { } }; 
struct c { void bar() { } }; 

मैं एक अधिभार सेट lambdas जो a स्पष्ट रूप से हैंडल से बाहर बनाना चाहते हैं, जबकि b और c एक सामान्य लैम्ब्डा एक auto पैरामीटर का उपयोग करने के साथ "पकड़ा" कर रहे हैं:

auto ol = overload([](a x) { x.foo(); }, 
        [](auto x){ x.bar(); }) 

जब मैं आह्वान ol(a{}):

  • क्लैंग ++ संकलित और अपेक्षित व्यवहार करता है: a पहले लैम्ब्डा "मैचों" से मेल खाता है, जबकि b और c दूसरे से मेल खाता है।

  • जी ++ निम्न त्रुटि के साथ, संकलन करने में विफल रहता है:

    error: 'struct a' has no member named 'bar' 
          [](auto x){ x.bar(); }; 
             ~~^~~ 
    

    ऐसा लगता है कि संकलक दूसरा लैम्ब्डा भले ही पहले एक एक तरह से बेहतर मुकाबला नहीं है का दृष्टांत की कोशिश करता है। उम्मीद है कि यह एक बग है, क्योंकि यह मेरे लिए अनजान लगता है।


नोट दोनों compilers ठीक से काम करने के बजाय लैम्ब्डा भाव मैं कुछ पुराने जमाने struct उदाहरणों का उपयोग करते हैं:

struct s0 
{ 
    auto operator()(a x) const { x.foo(); } 
}; 

struct s1 
{ 
    template <typename T> 
    auto operator()(T x) const { x.bar(); } 
}; 

auto os = overload(s0{}, s1{}); 
os(a{}); // OK! 

मैं lambdas मोटे तौर पर s0 के बराबर होने की अपेक्षा करेंगे और s1, तो यह और भी आश्चर्यजनक है। यहाँ

template <typename... Fs> 
struct overloader : Fs... 
{ 
    template <typename... FFwds> 
    overloader(FFwds&&... fs) : Fs{std::forward<FFwds>(fs)}... 
    { 
    } 

    using Fs::operator()...; 
}; 

template <typename... Fs> 
auto overload(Fs&&... fs) 
{ 
    return overloader<std::decay_t<Fs>...>{std::forward<Fs>(fs)...}; 
} 

और compilers के बीच अलग व्यवहार दिखा रहा है, एक live example on gcc.godbolt.org है:


इस तरह से मैं अधिभार सेट का निर्माण कर रहा हूँ है।


क्या यह एक g ++ बग है? या क्या मानक में कुछ ऐसा है जो इस स्थिति में struct उदाहरणों से लैम्ब्स अलग तरीके से व्यवहार करता है?

+0

हू, जब <<का उपयोग कर रहा था ...मानक दर्ज करें? सी ++ 17? –

+3

@ नियरफ्राइडमैन यिप, सी ++ 17 में, [पी 01 9 5] (http://wg21.link/p0195) – Barry

+2

के अलावा धन्यवाद: 'ओवरलोड' के लिए तर्क के रूप में फ़ंक्शन पॉइंटर्स लेने में सक्षम होना अच्छा है। ऐसा करने के लिए, ': Fs ...' को ': some_magic ...' के साथ बदलें, जहां 'some_magic' फ़ंक्शन पॉइंटर्स का पता लगाता है और इसे संग्रहीत करने वाले वर्ग में मानचित्र करता है, और बाकी सब कुछ अकेले छोड़ देता है। (लेकिन हो सकता है कि यह ओवरलोड एक सरलीकृत एमसीवीई है, जिस स्थिति में इसे अनदेखा किया जाता है) – Yakk

उत्तर

7

मुझे लगता है कि यह एक जीसीसी बग (80767 के रूप में प्रस्तुत) है [temp.inst]/9 की afoul चलाने:

An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement, unless such instantiation is required.

सामान्य लैम्ब्डा के operator()auto = a साथ की आवश्यकता नहीं है की इन्स्टेन्शियशन, इसलिए यह instantiated नहीं किया जाना चाहिए।

+4

त्रुटि रूपांतरण फ़ंक्शन टेम्पलेट को पॉइंटर-टू-फ़ंक्शन पर त्वरित करने से आता है, जिसका अर्थ है कि यह https://gcc.gnu.org/ का एक और संस्करण है बगजिला/show_bug.cgi? id = 71,117। –

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