9

मैं एक सी ++ 11 मुहावरा जो कहा जा सकता है "अतिभारित लैम्ब्डा" की जांच कर रहा हूँ के साथ:सी ++ 11 "अतिभारित लैम्ब्डा" variadic टेम्पलेट और चर कब्जा

variadic टेम्पलेट के साथ n कार्यों ओवरलोडिंग मेरे लिए बहुत आकर्षक लग रहा था, लेकिन यह पता चला है कि यह चर कब्जा करने के साथ काम नहीं किया: [&][=] ०१२३५९४९०५३३ के किसी भी

दूसरी ओर, तय 2-ary मामले नहीं था '(अपने स्थानीय जीसीसी 4.9.1 और ideone.com जीसीसी 5.1 के साथ) error: no match for call to '(overload<main(int, char**)::<lambda(int)>, main(int, char**)::<lambda(char*)> >) (char*&)':[&y] (और [this] आदि एक सदस्य समारोह में अगर) संकलन विफलता के लिए नेतृत्व उस समस्या को पीड़ित नहीं है। (Ideone.com पर पहले #if 0 से #if 1 को बदलने का प्रयास करें)

यहां क्या हो रहा है पर कोई विचार है? क्या यह एक कंपाइलर बग है, या मैं सी ++ 11/14 spec से विचलित हूं?

http://ideone.com/dnPqBF

#include <iostream> 
using namespace std; 

#if 0 
template <class F1, class F2> 
struct overload : F1, F2 { 
    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { } 

    using F1::operator(); 
    using F2::operator(); 
}; 

template <class F1, class F2> 
auto make_overload(F1 f1, F2 f2) { 
    return overload<F1, F2>(f1, f2); 
} 
#else 
template <class... Fs> 
struct overload; 

template <class F0, class... Frest> 
struct overload<F0, Frest...> : F0, overload<Frest...> { 
    overload(F0 f0, Frest... rest) : F0(f0), overload<Frest...>(rest...) {} 

    using F0::operator(); 
}; 

template <> 
struct overload<> { 
    overload() {} 
}; 

template <class... Fs> 
auto make_overload(Fs... fs) { 
    return overload<Fs...>(fs...); 
} 
#endif 

#if 0 
#define CAP 
#define PRINTY() 
#else 
#define CAP y 
#define PRINTY() cout << "int y==" << y << endl 
#endif 

int main(int argc, char *argv[]) { 
    int y = 123; 

    auto f = make_overload(
     [CAP] (int x) { cout << "int x==" << x << endl; PRINTY(); }, 
     [CAP] (char *cp) { cout << "char *cp==" << cp << endl; PRINTY(); }); 
    f(argc); 
    f(argv[0]); 
} 
+0

आप होना चाहिए ' ओवरलोड :: ऑपरेटर(); 'दूसरे कार्यान्वयन में, [डेमो] (http://coliru.stacked-crooked.com/a/c908c85a29e04004) –

+0

और [यही कारण है कि गैर-कैप्चरिंग लैम्बडास कार्यों के साथ ओवरलोडिंग] (http://coliru.stacked-crooked.com/a/dd9502d8e428c048) :-) –

+0

@ पियट rSkotnicki दिलचस्प है, लेकिन 'अधिभार :: ऑपरेटर() का उपयोग करके' स्थिति 'में सुधार नहीं किया है। – nodakai

उत्तर

8

अधिभार संकल्प कार्यों कि एक आम दायरे में मौजूद के लिए ही काम करता है। इसका मतलब है कि दूसरा कार्यान्वयन दूसरे अधिभार को खोजने में विफल रहता है क्योंकि आप overload<Frest...> से overload<F0, Frest...> में फ़ंक्शन कॉल ऑपरेटरों को आयात नहीं करते हैं।

हालांकि, एक गैर-कैप्चरिंग लैम्ब्डा प्रकार लैम्ब्डा के फ़ंक्शन कॉल ऑपरेटर के समान हस्ताक्षर के साथ एक फ़ंक्शन पॉइंटर में रूपांतरण ऑपरेटर को परिभाषित करता है। यह रूपांतरण ऑपरेटर नाम लुकअप द्वारा पाया जा सकता है, और जब आप कैप्चरिंग भाग को हटाते हैं तो यह वही होता है।

सही कार्यान्वयन, कि दोनों कैप्चरिंग और के लिए काम करता गैर पर कब्जा करने lambdas, और कहा कि हमेशा एक रूपांतरण ऑपरेटर के बजाय operator() कहता है, के रूप में देखना चाहिए इस प्रकार है:

template <class... Fs> 
struct overload; 

template <class F0, class... Frest> 
struct overload<F0, Frest...> : F0, overload<Frest...> 
{ 
    overload(F0 f0, Frest... rest) : F0(f0), overload<Frest...>(rest...) {} 

    using F0::operator(); 
    using overload<Frest...>::operator(); 
}; 

template <class F0> 
struct overload<F0> : F0 
{ 
    overload(F0 f0) : F0(f0) {} 

    using F0::operator(); 
}; 

template <class... Fs> 
auto make_overload(Fs... fs) 
{ 
    return overload<Fs...>(fs...); 
} 

DEMO

+1

ध्यान दें कि यदि आप एक ओवरलोड सेट में कई ओवरलोड (कहें, कुछ 100 से अधिक) चाहते हैं, तो आप रैखिक विरासत को लगभग संतुलित बाइनरी विरासत में बदलना चाहेंगे। और आप अपने डिजाइन पर पुनर्विचार करना चाहेंगे, क्योंकि आप एक बार में कुछ 100 भेड़ के बच्चे क्यों अधिक लोड कर रहे हैं? (इसके अलावा, बाइनरी संस्करण अधिक कोड है) – Yakk

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