2016-08-28 17 views
5

के साथ अधिभारित ऑपरेटर मैं मल्टी-टाइप मैप धारक पर काम कर रहा हूं। यह सभी आदिम प्रकारों और साथ ही structs के साथ भी काम करता है। बिंदु। हालांकि, अगर मैं एक समर्थित प्रकार (कॉलबैक के लिए इस्तेमाल किया) के रूप में std :: समारोह जोड़ना चाहते हैं तो संकलक शिकायत:std :: function पैरामीटर

MT.cpp: 426: 15: नहीं व्यवहार्य अतिभारित '='

मीट्रिक टन । एच: 31: 7: अभ्यर्थी समारोह (निहित प्रति असाइनमेंट ऑपरेटर) व्यवहार्य नहीं है: 'ज्ञात ' से कोई ज्ञात नहीं है ('lambda at MT.cpp: 426: 17)' to sharkLib :: MT ' पहले तर्क के लिए

MT.h: 31: 7: अभ्यर्थी कार्य (अंतर्निहित कदम असाइनमेंट ऑपरेटर) व्यवहार्य नहीं है: '(लैम्ब्डा ए से कोई ज्ञात रूपांतरण नहीं) टी MT.cpp: 426: 17) sharkLib ::

मैं वास्तव में = ऑपरेटर को ओवरलोड नहीं है, लेकिन बजाय 1 तर्क के लिए मीट्रिक टन '' में समर्थित प्रकार प्रति समर्पित निर्माता के साथ [] ओवरलोड।

protected: 
    map<string,MT> valueMap; 

public: 
    MT (int value); 
    MT (std::function<void(Ref*)> ccb); 
    virtual MT& operator[] (const char* key); 

सीपीपी

MT::MT (int value) 
{ 
    this->type = ValueType::intValue; 
    this->value.int_ = value; 
} 

MT::MT (std::function<void(Ref*)> value) 
{ 
    this->type = ValueType::ccbValue; 
    this->value.ccb_ = value; 
} 

MT& MT::operator[] (const char* key) 
{ 
    return this->valueMap[key]; 
} 

उपयोग

MT mt; 

mt["int"] = 1; 
mt["ccb"] = [](Ref *){ CCLOG("Pressed"); }; 

यह अंतिम पंक्ति त्रुटि के साथ एक है।

+1

संभवतः यहां उत्तर दिया गया: http: // stackoverflow।कॉम/प्रश्न/13358672/कैसे-टू-कन्वर्ट-ए-लैम्ब्डा-टू-ए-स्टडफंक्शन-उपयोग-टेम्पलेट्स – Chris

+0

क्या मुझे पूछने की हिम्मत है कि क्यों ctors और 'ऑपरेटर []' एक ही प्रकार पर हैं? – Yakk

उत्तर

4

समस्या यह है कि आप एक डबल रूपांतरण अनुक्रम का उपयोग करने की कोशिश कर रहे है: std::function<void(Ref*)>

  • को

    1. लैम्ब्डा समारोह से std::function<void(Ref*)> से MT

    कि चारों ओर रास्ते पर दोहरे रूपांतरण की आवश्यकता को दूर करने के लिए, या तो

    mt["cast via function"] = static_cast<std::function<void(Ref*)>([](Ref*){ /*...*/ }); 
    mt["cast via MT"] = MT([](Ref*){ /*...*/ }); 
    

    का उपयोग कर आप MT करने के लिए एक समारोह प्रकार से रूपांतरण आप MT के एक निर्माता जो सीधे समारोह लेता आवश्यकता होगी समर्थन करना चाहते हैं है प्रकार। अपने अन्य निर्माताओं की मान लिया जाये कि कोई भी एक स्वेच्छापूर्ण टेम्पलेट का उपयोग कर के साथ लिखा है, तो आप सिर्फ आप पहले से ही एक अन्य प्रकार आप उपयुक्त परिस्थितियों, उदा उपयोग करने की आवश्यकता होगी के लिए एक स्वेच्छापूर्ण टेम्पलेट का उपयोग कर रहे हैं, तो

    template <typename Fun> 
    MT::MT(Fun&& fun) 
        : type(ValueType::ccbValue) { 
        this->value.ccb = std::forward<Fun>(fun); 
    } 
    

    जोड़ सकता है std::is_convertible<Fun, std::function<void(Ref*)>>::value, ओवरलोड लोड से संबंधित निर्माता (ओं) को हटाने के लिए एक उपयुक्त SFINAE-दृष्टिकोण के साथ।

  • +0

    क्यों अपने कन्स्ट्रक्टर में sfinae लाइन स्पष्ट रूप से शामिल नहीं है? – Yakk

    +0

    @Yakk: यदि कन्स्ट्रक्टर एक अनजान टेम्पलेट वाला एकमात्र है तो यह अनावश्यक है और यदि यह नहीं है तो यह अपर्याप्त है क्योंकि अन्य कन्स्ट्रक्टर को विपरीत मामले के साथ संभालना होगा। तो यह इसमें व्यर्थ लगता है। –

    +1

    'एमटी कॉन्स एंड '' और' एमटी ''' एमटी एंड' या 'एमटी कॉन्स और' नहीं 'के लिए 'मजेदार और' पसंद करेंगे? इसके अलावा, बेहतर त्रुटि संदेश। [लाइव उदाहरण] (http://coliru.stacked-crooked.com/a/add8adee5cf29d93)। असल में आपको कभी भी एक गैर-SFINAE संरक्षित एक-तर्क सही अग्रेषण ctor नहीं होना चाहिए। – Yakk

    2

    ठीक है, क्रिस मुझे प्रेरित है और यह समाधान है:

    typedef std::function<void(Ref*)> ClickCallback; 
    ... 
        MT (ClickCallback ccb); 
    ... 
    mt["ccb"] = (ClickCallback) [](Ref *){ CCLOG("Pressed "); };; 
    
    +1

    स्पष्ट सी शैली कास्ट सामान्य रूप से एक बुरा विचार है। और आपको इसकी आवश्यकता नहीं है। – Yakk

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