2011-10-08 17 views
7

समस्याएं मुझे परेशान करने में यह समस्या है। मैं FSM वर्ग है जो कॉलबैकटेम्पलेट पैरामीटर के रूप में कार्य

class FSM 
{ 
public: 

typedef bool (FSM::*InCallback_t)(int); 
typedef std::map< std::string, InCallback_t > Table; 

// Since I would like to allow the user to register both functors and class member functions 
template< typename Callback_t, bool (Callback_t::*CallbackFunct_t)(int) > 
bool callback(int x) 
{ 
    return (Callback_t().*CallbackFunct_t)(x); 
} 

void addCallback(const std::string& iKey, InCallback_t iCallback) 
{ 
    _table.insert(std::make_pair(iKey, iCallback)); 
} 

    [ ... ] 

private: 
    Table _table; 
}; 

के सहयोगी कुंजी और कुछ कॉलबैक कक्षाएं

class CallbackBase 
{ 
public: 

    bool operator()(int x){ return doCall(x); } 

private: 
    virtual bool doCall(int x){ return true; } 
}; 


class Callback: public CallbackBase 
{ 
private: 
    bool doCall(int x) 
    { 
     std::cout << "Callback\n"; 
     return true; 
    } 
}; 

अब अगर मुख्य में मुझे क्या करना:

FSM aFSM; 
// OK 
aFSM.addCallback("one", &FSM::callback< CallbackBase, &CallbackBase::operator() >); 
// KO 
aFSM.addCallback("two", &FSM::callback< Callback, &Callback::operator() >); 

पहली कॉल, ठीक है में दूसरा एक कंपाइलर शिकायत करता है:

Test.cpp: In function ‘int main(int, char**)’: 
Test.cpp:104:77: error: no matching function for call to ‘FSM::addCallback(const char [4], <unresolved overloaded function type>)’ 
Test.cpp:104:77: note: candidate is: 
Test.cpp:24:7: note: void FSM::addCallback(const string&, FSM::InCallback_t) 
Test.cpp:24:7: note: no known conversion for argument 2 from ‘<unresolved overloaded function type>’ to ‘FSM::InCallback_t’ 

भी ध्यान दें कि निम्नलिखित ठीक है

typedef bool (Callback::*Function_t)(int); 
Function_t aFunction = &Callback::operator(); 
(Callback().*aFunction)(5); 

किसी भी विचार? आपकी मदद के लिए अग्रिम धन्यवाद।

सिमोन

+2

एक कंपाइलर बग की तरह लगता है। : | – Nawaz

+0

हां मुझे यह भी माना जाता है। यह काफी अजीब है – Simone

+0

मुझे व्युत्पन्न वर्ग के सदस्य कार्य-सूचक के साथ बेस-स्तरीय फ़ंक्शंस (या ऑपरेटरों) का उपयोग करके, इसके साथ कुछ समस्याएं थीं। कम से कम एमएसवीसी में, यह सिर्फ टेम्पलेट्स में काम नहीं करता है। – Xeo

उत्तर

2

आपने कॉलबैक :: ऑपरेटर() को परिभाषित नहीं किया है। कॉलबैक के लिए कॉलबैक के लिए कोई साउंड फ़ंक्शन नहीं है जो कॉलबैकबेस से फ़ंक्शन है जो कॉलबैकबेस और पैरामीटर के रूप में एक int लेता है! यही कारण है कि संकलक "अनसुलझा अधिभारित फ़ंक्शन प्रकार" के बारे में moans।

विरासत समारोह का प्रकार बूल (कॉलबैकबेस :: * ऑपरेटर()) (int) है। यह फ़ंक्शन स्वचालित रूप से एक बूल (कॉलबैक :: * ऑपरेटर()) (int) में परिवर्तित हो सकता है क्योंकि आप हमेशा उस फ़ंक्शन पर कॉलबैक लागू कर सकते हैं जो केवल कॉलबैकबेस स्वीकार करता है। यही कारण है कि निम्नलिखित कार्य करता है - यह एक स्वचालित कलाकार है जो वहां हो रहा है। जब कॉलबैक instanciating

template< typename Callback_t, bool (Callback_t::*CallbackFunct_t)(int) > 
with: Callback_t = Callback, CallbackFunct_t = bool (CallbackBase::*CallbackFunct_t)(int) 

इस प्रकार है कि Callback_t और प्रकार समारोह सूचक द्वारा अपेक्षित के माध्यम से दिए गए के बाद से काम नहीं करता है मेल नहीं खाते:

typedef bool (Callback::*Function_t)(int); 
Function_t aFunction = &Callback::operator(); 
समस्या

टेम्पलेट प्रकार कटौती के साथ होता है समारोह। टाइप कटौती होने से पहले आप फ़ंक्शन पॉइंटर की स्पष्ट कलाकार (कॉलबैक :: * ऑपरेटर()) (int) के साथ समस्या का समाधान कर सकते हैं। यदि आप कॉलबैक फ़ंक्शन को निम्न में बदलते हैं तो आपको दो प्रकारों को समान होने की आवश्यकता नहीं होती है और यह कलाकारों के बिना संकलित होती है।

template< typename Callback_t> 
bool callback(int x) 
{ 
    return Callback_t()(x); 
} 

मुझे समझ में नहीं आता कि आप वर्चुअल फ़ंक्शन क्यों जोड़ते हैं। निम्नलिखित कुछ भी नहीं करेंगे, अधिक सरल और पठनीय और तेज भी हो (कोई आभासी फ़ंक्शन कॉल नहीं)? डकॉल फ़ंक्शन को सार्वजनिक होना आवश्यक होगा।

template< typename Callback_t> 
bool callback(int x) 
{ 
    return Callback_t().doCall(x); 
} 

कॉलबैक फ़ंक्शन स्थिर करने के लिए एक और सुधार होगा। यदि डकॉल फ़ंक्शन स्थिर होंगे तो यह और भी आसान होगा - इससे कॉलबैक फ़ंक्शन अप्रचलित हो जाएगा और डॉक कॉल करने के लिए अस्थायी बनाने से बच जाएगा।

+0

आपके उत्तर के लिए धन्यवाद। कुछ टिप्पणी बिंदु के बारे में यदि कॉलबैक :: ऑपरेटर() मौजूद है। यह अस्तित्व में है क्योंकि इसे बेस क्लास से विरासत में मिला है और असल में कोड की आखिरी तीन पंक्तियों में मैंने प्रश्न में सही तरीके से काम किया है। वास्तव में यह मुझे एक कंपाइलर बग लगता है। हां यह सच है कि मैं फ़ंक्शन पॉइंट को टेम्पलेट पैरामीटर के रूप में हटा सकता हूं लेकिन उस स्थिति में मैं केवल फ़ैक्टर ऑब्जेक्ट को संभाल सकता था, जबकि वास्तव में मुझे अधिक लचीला होना पसंद होता था, जिससे उपयोगकर्ता को एकल कार्य करने के मामले में सदस्य फ़ंक्शंस निर्दिष्ट करने की इजाजत मिलती सदस्य कॉल के रूप में सभी कॉलबैक लागू करने वाली कक्षा। ... – Simone

+0

.. क्यों मैंने ऑपरेटर() और वर्चुअल डॉकॉल को परिभाषित किया है। यह टेम्पलेट विधि नामक एक पैटर्न है। हां ऊपर दिए गए उदाहरण में यह बेकार है लेकिन आप कल्पना कर सकते हैं कि ऑपरेटर() में कॉलबैकबेस में प्रत्येक व्युत्पन्न कक्षा में लागू कॉलबैक फ़ंक्शन के कॉल के पहले और बाद में निष्पादित कुछ प्री-ऑपरेशंस और पोस्ट-ऑपरेशंस लागू किए गए हैं। एक उदाहरण doCall के निष्पादन समय के बारे में आंकड़े ले सकता है। – Simone

+0

@ सिमोन मैं एक कंपाइलर बग में विश्वास नहीं करता हूं। मैंने आपके कोड को जीसीसी और विजुअल स्टूडियो पर उसी परिणाम के साथ संकलित करने का प्रयास किया। विजुअल स्टूडियो में त्रुटि संदेश है: 'बूल (__thiscall CallbackBase :: *) (int)' to 'bool (__thiscall Callback :: * const) (int)' से कनवर्ट नहीं किया जा सकता है। कोई फ़ंक्शन कॉलबैक :: ऑपरेटर() नहीं है, यह केवल बेस क्लास से कॉल करता है। निम्नलिखित में से किसी भी संकलित कंपाइलर में संकलित नहीं होता है: टाइपपीफ शून्य (कॉलबैक :: * func) (int); func f = और कॉलबैक :: ऑपरेटर(); –

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

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