2012-02-08 9 views
40

मैं एक कक्षा बनाना चाहता हूं जहां क्लाइंट कक्षा के एक क्षेत्र के रूप में []() -> void {} जैसे लैम्ब्डा अभिव्यक्ति को स्टोर कर सकता है, लेकिन मैं यह नहीं समझ सकता कि ऐसा कैसे करें। One answer suggested using decltype, जिसकी मैंने सफलता नहीं की। यहां एक ideone source link है। नीचे दिए गए स्रोत और परिणाम है:मैं सी ++ 11 में कक्षा के क्षेत्र के रूप में लैम्ब्डा अभिव्यक्ति कैसे संग्रहीत कर सकता हूं?

#include <cstdio> 
auto voidLambda = []()->void{}; 

class MyClass { 
public: 
    decltype(voidLambda) t; 
    MyClass(decltype(voidLambda) t) { 
     this->t = t; 
    } 
}; 

int main() { 
    MyClass([] { 
     printf("hi"); 
    }); 
} 

परिणाम:

prog.cpp: In constructor 'MyClass::MyClass(<lambda()>)': 
prog.cpp:3:79: error: no matching function for call to '<lambda()>::__lambda0()' 
prog.cpp:2:20: note: candidates are: <lambda()>::<lambda>(const<lambda()>&) 
prog.cpp:2:20: note:     <lambda()>::<lambda>(<lambda()>&&) 
prog.cpp:3:88: error: no match for 'operator=' in '((MyClass*)this)->MyClass::t = t' 
prog.cpp: In function 'int main()': 
prog.cpp:5:27: error: no matching function for call to 'MyClass::MyClass(main()::<lambda()>)' 
prog.cpp:3:48: note: candidates are: MyClass::MyClass(<lambda()>) 
prog.cpp:3:14: note:     MyClass::MyClass(const MyClass&) 

किसी को भी ऐसा करने के तरीके पता है?

+5

हर लैम्ब्डा अभिव्यक्ति यह अपनी अनूठी प्रकार है बनाता है। 'ऑटो ए = []() {} में; ऑटो बी = []() {}; '' ए 'और 'बी' एक ही प्रकार के नहीं हैं। – bames53

+1

दुर्भाग्य से 'संरचना ए {ऑटो x = 0; }; 'अनुमति नहीं है। –

उत्तर

40

यदि आप कक्षा के सदस्य को लैम्ब्डा अभिव्यक्ति के रूप में चाहते हैं, तो std::function<> रैपर प्रकार (<functional> शीर्षलेख से) का उपयोग करने पर विचार करें, जो किसी भी कॉल करने योग्य फ़ंक्शन को पकड़ सकता है। उदाहरण के लिए:

std::function<int()> myFunction = []() { return 0; } 
myFunction(); // Returns 0; 

इस तरह, आपको लैम्ब्डा अभिव्यक्ति के प्रकार को जानने की आवश्यकता नहीं है। आप उचित फ़ंक्शन प्रकार के std::function<> को स्टोर कर सकते हैं, और टेम्पलेट सिस्टम आपके लिए सभी प्रकारों को संभाल लेगा। अधिक आम तौर पर, उपयुक्त हस्ताक्षर की किसी भी कॉल करने योग्य इकाई को std::function<> पर असाइन किया जा सकता है, भले ही उस मज़ेदार का वास्तविक प्रकार अज्ञात (लैम्बडास के मामले में) या वास्तव में जटिल हो।

std::function टेम्पलेट के अंदर का प्रकार उस फ़ंक्शन से संबंधित फ़ंक्शन प्रकार होना चाहिए जिसे आप स्टोर करना चाहते हैं। तो, उदाहरण के लिए, दो int एस में एक फ़ंक्शन संग्रहीत करने के लिए और शून्य लौटाता है, तो आप std::function<void (int, int)> बनायेंगे। ऐसे फ़ंक्शन के लिए जो कोई पैरामीटर नहीं लेता है और int देता है, तो आप std::function<int()> का उपयोग करेंगे। आपके मामले में, जब से तुम एक समारोह है कि कोई पैरामीटर लेता है और void रिटर्न चाहते हैं, आप कुछ इस तरह चाहते हैं:

class MyClass { 
public: 
    std::function<void()> function; 
    MyClass(std::function<void()> f) : function(f) { 
     // Handled in initializer list 
    } 
}; 

int main() { 
    MyClass([] { 
     printf("hi") 
    }) mc; // Should be just fine. 
} 

आशा इस मदद करता है!

+0

प्रश्न: '-> शून्य' वास्तव में यहां जरूरी है? मुझे पता है कि रिटर्न क्लॉज को कई परिस्थितियों में छोड़ा जा सकता है (और इस प्रकार कम किया जा सकता है) और यह मुझे एक आसान मामला शुरू करने के रूप में मारता है (कोई 'वापसी' नहीं)। –

+0

@ MatthieuM.- मुझे वास्तव में यकीन नहीं है! मैं इस धारणा के तहत था कि आपको यह होना था, लेकिन अगर मुझे गलत लगता है तो मुझे यह जवाब अपडेट करने में खुशी होगी। – templatetypedef

+0

ठीक है, मैं भी सीख रहा हूं, इसलिए मैं उम्मीद कर रहा था * आपको * पता होगा :) –

7

एक ही रास्ता मैं एक कक्षा में एक लैम्ब्डा स्टोर करने के लिए के बारे में सोच सकते हैं एक सहायक make_ समारोह के साथ एक टेम्पलेट का उपयोग करने के लिए है:

#include <cstdio> 
#include <utility> 

template<class Lambda> 
class MyClass { 
    Lambda _t; 
public: 
    MyClass(Lambda &&t) : _t(std::forward<Lambda>(t)) { 
     _t(); 
    } 
}; 

template<class Lambda> 
MyClass<Lambda> make_myclass(Lambda &&t) { 
    return { std::forward<Lambda>(t) }; 
} 

int main() { 
    make_myclass([] { 
     printf("hi"); 
    }); 
} 
+4

इस सहायक 'make_myclass' को पेश करके टेम्पलेट तर्क निर्दिष्ट करने की आवश्यकता को रोकता है। वह [ऑब्जेक्ट जनरेटर idiom] है (https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Object_Generator)। – mucaho