c ++ 0x: संदर्भ द्वारा पैरामीटर के रूप में एक लंबो प्राप्त करने का उचित तरीका


85

एक फ़ंक्शन को परिभाषित करने का सही तरीका क्या है जो int->intसंदर्भ द्वारा लंबोर्ड पैरामीटर प्राप्त करता है ?

void f(std::function< int(int) >& lambda);

या

void f(auto& lambda);

मुझे यकीन नहीं है कि अंतिम रूप भी कानूनी वाक्यविन्यास है।

क्या लैम्बडा पैरामीटर को परिभाषित करने के अन्य तरीके हैं?


10
आपको संदर्भ द्वारा लंबोदर की आवश्यकता क्यों होगी? क्या आपका मतलब है const&?
deft_code

जवाबों:


84

आपके पास कोई autoपैरामीटर नहीं हो सकता । आपके पास मूल रूप से दो विकल्प हैं:

विकल्प # 1: std::functionजैसा आपने दिखाया है उसका उपयोग करें ।

विकल्प # 2: टेम्पलेट पैरामीटर का उपयोग करें:

template<typename F>
void f(F &lambda) { /* ... */}

विकल्प # 2, कुछ मामलों में, अधिक कुशल हो सकता है, क्योंकि यह एम्बेडेड लैम्ब्डा फ़ंक्शन ऑब्जेक्ट के लिए संभावित हीप आवंटन से बच सकता है, लेकिन यह तभी संभव है जब fइसे हेडर में टेम्प्लेट फ़ंक्शन के रूप में रखा जा सकता है। यह किसी भी टेम्प्लेट के रूप में संकलन समय और I-कैश फुटप्रिंट भी बढ़ा सकता है। ध्यान दें कि इसका कोई प्रभाव नहीं हो सकता है, जैसे कि लैम्ब्डा फ़ंक्शन ऑब्जेक्ट काफी छोटा है यह std::functionऑब्जेक्ट में इनलाइन का प्रतिनिधित्व कर सकता है ।


1
टेम्प्लेट्स I-कैश फुटप्रिंट में भी सुधार कर सकते हैं, सामान्य गैर-स्थानीय कोड पर जंप को समाप्त करके (इस मामले में, सीधे अपने लैम्ब्डा को निष्पादित करें, सामान्य प्रयोजन के std::functionआवरण के माध्यम से कूदने के बिना )
jalf

5
यह उद्धरण, "अगर लंबो फंक्शन ऑब्जेक्ट काफी छोटा है तो इसे std::functionऑब्जेक्ट में इनलाइन का प्रतिनिधित्व किया जा सकता है " भ्रामक है। लैम्ब्डा हमेशा इनलाइन के लिए उपलब्ध हैं (कंपाइलर कोर्स का चयन नहीं कर सकता है)। std::functionकार्यान्वयन आम तौर पर ढेर आवंटन से बचने के लिए छोटी वस्तु अनुकूलन का उपयोग करता है। यदि एक लैम्ब्डा के पास एक छोटी सी पर्याप्त कैप्चर सूची है, तो उसे std::functionढेर का उपयोग किए बिना संग्रहीत किया जाएगा । इसके अलावा एक मेमने के आकार का कोई वास्तविक अर्थ नहीं है।
deft_code

2
@bdonlan: वैसे, क्यों नहीं है &में void f(F & lambda)?
नवाज

2
@bdonlan: लेकिन कांस्टेबल और मानता है कि लंबोदर (कैप्चर-बाय-वैल्यू) के सदस्यों को नहीं बदला जा सकता है। जो उपयोगकर्ता नहीं चाहता है।
निकोल बोलस

2
@bdonlan यह एक समय हो गया है, लेकिन गैर-कास्ट संदर्भ के रूप में पास होने से फ़ंक्शन कॉल में अस्थायी लैम्ब्डा के निर्माण की अनुमति नहीं है। एक आर-मूल्य संदर्भ यहां सबसे अच्छा होगा।
zennhoy

46

मैं इस प्रकार उपयोग करूंगा template:

template<typename Functor>
void f(Functor functor)
{
   cout << functor(10) << endl;
}

int g(int x)
{
    return x * x;
}
int main() 
{
    auto lambda = [] (int x) { cout << x * 50 << endl; return x * 100; };
    f(lambda); //pass lambda
    f(g);      //pass function 
}

आउटपुट:

500
1000
100

डेमो: http://www.ideone.com/EayVq


12

मुझे पता है कि यह 7 साल हो गया है, लेकिन यहाँ एक तरीका है जिसका किसी और ने उल्लेख नहीं किया है:

void foo(void (*f)(int)){
    std::cout<<"foo"<<std::endl;
    f(1); // calls lambda which takes an int and returns void
}
int main(){
    foo([](int a){std::cout<<"lambda "<<a<<std::endl;});
}

कौन से आउटपुट:

foo
lambda 1

टेम्प्लेट या std :: फ़ंक्शन की कोई आवश्यकता नहीं है


12
यह केवल लैंबडास तक सीमित है जो फ़ंक्शन पॉइंटर्स (लैंबडास डब्ल्यू / ओ कैप्चर) को क्षय कर सकता है, और सटीक हस्ताक्षर निर्दिष्ट करने की भी आवश्यकता है ( std::functionहालांकि मामले के लिए ) हालांकि टेम्पर्ड संस्करण में यह सीमा नहीं है।
एंड्री टाइलिचको

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.