2011-10-10 16 views
37
#include <vector> 
#include <algorithm> 

void foo(int) 
{ 
} 

int main() 
{ 
    std::vector<int> v({ 1,2,3 }); 

    std::for_each(v.begin(), v.end(), [](auto it) { foo(it+5); }); 
} 

जब संकलित में ऑटो का प्रयोग, उदाहरण के ऊपर शुरू होता है इस तरह त्रुटि उत्पादन:एक लैम्ब्डा समारोह

h4.cpp: In function 'int main()': 
h4.cpp:13:47: error: parameter declared 'auto' 
h4.cpp: In lambda function: 
h4.cpp:13:59: error: 'it' was not declared in this scope 

यह मतलब यह है कि कीवर्ड auto लैम्ब्डा भाव में नहीं किया जाना चाहिए?

यह काम करता है:

std::for_each(v.begin(), v.end(), [](int it) { foo(it+5); }); 

क्यों ऑटो कीवर्ड के साथ संस्करण काम नहीं करता है?

+1

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

+3

हमें अगले मानक में वास्तव में पॉलिमॉर्फिक लैम्बडास (एकेए निहित टेम्पलेट्स) की आवश्यकता है। यह सवाल सिर्फ कई मामलों में से एक है जहां लोग सिर्फ 'ऑटो' इस तरह से काम करते हैं। मुझे कोई कारण नहीं दिखता है। –

+0

deft_code, मैं तुम्हारे साथ हूँ।यह ऑटो के लिए एक तार्किक उपयोग मामला है। – Robert

उत्तर

63

ऑटो कीवर्ड फ़ंक्शन तर्कों के प्रकार के रूप में काम नहीं करता है। यदि आप लैम्ब्डा फ़ंक्शंस में वास्तविक प्रकार का उपयोग नहीं करना चाहते हैं, तो आप नीचे दिए गए कोड का उपयोग कर सकते हैं।

for_each(begin(v), end(v), [](decltype(*begin(v)) it){ 
     foo(it + 5);   
}); 
+37

हम [सी ++ 14] (http://en.wikipedia.org/wiki/C%2B%2B14#Generic_lambdas) में लैम्बडास में 'ऑटो' समर्थन प्राप्त करने जा रहे हैं। –

+0

'decltype' में 'शुरू (v)' से पहले स्टार को याद करें। आप मान प्रकार को इटरेटर प्रकार नहीं चाहते हैं। (जब आप विफल हो जाते हैं तो त्रुटि संदेश रहस्यमय होंगे)। –

4

लैम्ब्डा के प्रकार से पहले संकलक भी std::for_each का दृष्टांत कर सकते हैं जाना जाता है की जरूरत है। दूसरी तरफ, भले ही यह सैद्धांतिक रूप से संभव हो, auto केवल for_each के बाद ही किया जा सकता है यह देखकर तुरंत किया जा सकता है कि कैसे मज़ेदार को बुलाया जाता है।

सभी संभव पर हैं, के बारे में for_each भूल जाते हैं, और छोरों जो बहुत आसान कर रहे हैं के लिए सीमा के आधार पर का उपयोग करें:

for (int it : v) { 
    foo(it + 5); 
} 

यह भी auto (और auto& और const auto&) के साथ अच्छी तरह से सामना करना चाहिए।

for (auto it : v) { 
    foo(it + 5); 
} 
+0

हां लेकिन यह केवल for_each के साथ काम करता है, न कि अन्य एल्गोरिदम। जैसे आप एक लैम्ब्डा को सॉर्ट करना चाहते हैं। – CashCow

20

इस पर साक्षात्कार के दौरान हर्ब सटर द्वारा संक्षेप में चर्चा की गई। auto तर्क के लिए आपका मांग वास्तव में मांग की है कि किसी भी समारोह auto साथ declarable होना चाहिए इस तरह, से अलग नहीं है:

auto add(auto a, auto b) -> decltype(a + b) { return a + b; } 

हालांकि, ध्यान दें कि यह वास्तव में एक समारोह नहीं है, बल्कि यह है एक टेम्पलेट समारोह, के लिए समान:

template <typename S, typename T> 
auto add(S a, T b) -> decltype(a + b) { return a + b; } 

तो तुम अनिवार्य रूप से एक सुविधा के लिए पूछ रहे हैं किसी टेम्प्लेट में अपने तर्कों को बदलने के द्वारा किसी भी समारोह चालू करने के लिए। चूंकि टेम्पलेट्स सी ++ की प्रकार प्रणाली में एक बहुत ही अलग प्रकार की इकाई हैं (टेम्पलेट्स के लिए सभी विशेष नियमों के बारे में सोचें, जैसे कि दो चरण के लुकअप और कटौती), यह अप्रत्याशित रैमिकेशंस के साथ कट्टरपंथी डिज़ाइन परिवर्तन होगा, जो निश्चित रूप से ' किसी भी समय मानक में होने जा रहा है।

+1

नहीं, पूछना या मांग नहीं करना :) मैं बस सोच रहा था कि यह क्यों काम नहीं करता है। –

+5

ठीक है, यह अनिवार्य रूप से एक ही कारण है कि "सभी फ़ंक्शंस टेम्पलेट क्यों नहीं हैं" - यह भाषा के डिज़ाइन में फिट नहीं है। –

16

सी ++ 14 लैम्ब्डा फ़ंक्शन (जेनेरिक लैम्ब्डा फ़ंक्शन) पैरामीटर को ऑटो के साथ घोषित करने की अनुमति देता है।

auto multiply = [](auto a, auto b) {return a*b;}; 

जानकारी के लिए: http://en.cppreference.com/w/cpp/language/lambda

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