2015-01-03 19 views
10

निम्न उदाहरणसमारोह अधिभार लैम्ब्डा का उपयोग कर समारोह हस्ताक्षर

void foo(const std::function<int()>& f) { 
    std::cout << f() << std::endl; 
} 

void foo(const std::function<int(int x)>& f) { 
std::cout << f(5) << std::endl; 
} 

int main() { 
    foo([](){return 3;}); 

    foo([](int x){return x;}); 
} 

यह संकलन नहीं करता, क्योंकि foo करने के लिए कॉल अस्पष्ट होना कहा जाता है पर विचार करें। जहां तक ​​मैं समझता हूं कि यह तथ्य इस तथ्य के कारण है कि लैम्ब्डा फ़ंक्शन std::function से पहले नहीं है, लेकिन उसे std::function कन्स्ट्रक्टर है जो मनमाने ढंग से तर्क लेता है।

शायद कोई मुझे समझा सकता है कि कोई भी एक अंतर्निहित रचनाकार क्यों बनायेगा जो मनमाने ढंग से तर्क लेता है। हालांकि मेरा आकस्मिक सवाल यह है कि क्या कोई कामकाज है, जो कि foo फ़ंक्शन को अधिभारित करने के लिए लैम्ब्डा फ़ंक्शंस के फ़ंक्शन हस्ताक्षर का उपयोग करने की अनुमति देता है। मैंने फ़ंक्शन पॉइंटर्स का प्रयास किया है, लेकिन यह काम नहीं किया क्योंकि लैम्ब्डा फ़ंक्शंस को कैप्चर करना सामान्य फ़ंक्शन पॉइंटर पर नहीं डाला जा सकता है।

किसी भी मदद का स्वागत है।

+7

यह शायद एमएसवीसी में एक बग है। यह क्लैंग/जीसीसी में काम करता है। –

+2

ओह माइक्रोसॉफ्ट, आप बहुत मजेदार –

+0

[मेरे लिए काम करता है] (http://ideone.com/XmAgLG)। आप किस कंपाइलर का उपयोग कर रहे हैं? –

उत्तर

15

आपका कंपाइलर सी ++ 11 के अनुसार सही है। सी ++ 14 में, एक नियम जोड़ा जाता है जो कहता है कि कन्स्ट्रक्टर टेम्पलेट ओवरलोड रिज़ॉल्यूशन में भाग नहीं लेगा जब तक कि तर्क का प्रकार वास्तव में std::function के तर्क प्रकारों के साथ कॉल करने योग्य नहीं है। इसलिए, यह कोड C++ 14 में संकलित होना चाहिए, लेकिन C++ 11 में नहीं। सी ++ 11 में एक निरीक्षण होने के लिए इस पर विचार करें। एसटीडी का उपयोग करने के

foo(std::function<int()>([](){return 3;})); 
+0

स्पष्टीकरण के लिए धन्यवाद। टिप्पणियों के बाद मैंने जीसीसी 4.8 (और '-std = C++ 11') का उपयोग करके इसे आजमाया और यह काम किया। किसी भी तरह मजाकिया है कि जीसीसी का नया संस्करण सख्ती से सही सी ++ 11 का उपयोग नहीं करता है। – Haatschii

+1

@Haatschii यह सी ++ 11 मानक में एक दोष है; कंपाइलर/लाइब्रेरी देव आमतौर पर पीछे हटने वाले फ़िक्स को लागू करते हैं।(इसके अलावा, यह सी ++ 11 में यूबी था, इसलिए सी ++ 14 व्यवहार की अनुमति है।) –

4

http://coliru.stacked-crooked.com/a/26bd4c7e9b88bbd0

एक वैकल्पिक :: समारोह टेम्पलेट का उपयोग करने के लिए है:

अभी के लिए, आप इस के आसपास स्पष्ट रूपांतरण द्वारा काम कर सकते हैं। टेम्पलेट std :: function से जुड़े स्मृति आवंटन ओवरहेड से बचें। टेम्पलेट प्रकार की कटौती मशीनरी सही प्रकार के लैम्ब्डा को कम कर देगी ताकि कॉल साइट कास्ट दूर हो जाए। हालांकि आप अभी भी नो-एर्ग बनाम तर्क मामले के लिए ओवरलोड को असंबद्ध कर चुके हैं।

आप ट्रेलिंग रिटर्न प्रकारों के साथ एक चाल का उपयोग कर ऐसा कर सकते हैं जो enable_if के समान व्यवहार करता है।

template<typename Callable> 
auto baz(Callable c) 
    -> decltype(c(5), void()) 
{ 
    std::cout << c(5) << std::endl; 
} 

baz के ऊपर अधिभार केवल एक वैध अधिभार उम्मीदवार जब टेम्पलेट पैरामीटर प्रतिदेय की 5.

एक तर्क आप इस के शीर्ष पर और अधिक उन्नत तंत्र डाल सकते हैं इसे बनाने के लिए साथ कहा जा सकता है किया जाएगा अधिक सामान्य (यानी कॉल करने योग्य में तर्कों का चरम पैक विस्तार) लेकिन मैं काम कर रहे बुनियादी तंत्र को दिखाना चाहता था।

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