2009-03-14 18 views
7

मैं सोच रहा था कि सी ++ में ऐसा करने का कोई तरीका है या नहीं?विभिन्न प्रकार के बढ़ावा कार्यों का नक्शा?

void func1(const std::string& s) 
{ 
std::cout << s << std::endl; 
} 

void func2(int me) 
{ 
std::cout << me << std::endl; 
} 

int main() 
{ 
std::map<std::string, boost::function<???> > a_map; 

a_map["func1"] = &func1; 
a_map["func1"]("HELLO"); 

} 

क्या बूस्ट फ़ंक्शन और मानचित्र का उपयोग करके मेरे ऊपर क्या करने का कोई तरीका है?

+0

मान लें आप नक्शे में मूल्यों और कार्यों स्टोर कर सकते हैं, आप कैसे तत्वों को मैप करने तक पहुँचने चाहते हैं? – bayda

उत्तर

2

वहाँ कार्यों को स्टोर करने के तरीके, समस्या है, वांछित तर्क के साथ समारोह कॉल करने के लिए सक्षम होने के लिए आप चाहते हैं पता करने के लिए कर रहे हैं वैसे भी फ़ंक्शन के हस्ताक्षर को कॉल करना, और यदि आपके पास वह जानकारी है, तो आप अलग-अलग मानचित्रों का भी उपयोग कर सकते हैं, या boost :: function से अधिक जटिल ऑब्जेक्ट का उपयोग कर सकते हैं।

class MultiFunc 
{ 
protected: 
    MultiFunc() {} 

public: 
    typedef void (*stringFunc)(const std::string&); 
    typedef void (*intFunc)(int); 

    static MultiFunc *Create(stringFunc function); 
    static MultiFunc *Create(intFunc function); 

    virtual void operator()(const string &) { throw exception(); } 
    virtual void operator()(int) { throw exception(); } 
    virtual ~MultiFunc(); 
}; 

class MultiFuncString : public MultiFunc 
{ 
private: 
    stringFunc Function; 
public: 
    MultiFuncString(stringFunc function) : Function(function) {} 
    virtual void operator()(const string &arg) { Function(arg); } 
}; 

class MultiFuncInt : public MultiFunc 
{ 
private: 
    intFunc Function; 
public: 
    MultiFuncInt(intFunc function) : Function(function) {} 
    virtual void operator()(int arg) { Function(arg); } 
}; 

MultiFunc *MultiFunc::Create(MultiFunc::stringFunc function) 
{ 
    return new MultiFuncString(function); 
} 
MultiFunc *MultiFunc::Create(MultiFunc::intFunc function) 
{ 
    return new MultiFuncInt(function); 
} 

void func1(const std::string& s) 
{ 
std::cout << s << std::endl; 
} 
void func2(int me) 
{ 
std::cout << me << std::endl; 
} 

int main() 
{ 
    map<string, MultiFunc *> a_map; 
    a_map["func1"] = MultiFunc::Create(&func1); 
    (*a_map["func1"])("Hello"); 
    a_map["func2"] = MultiFunc::Create(&func2); 
    (*a_map["func2"])(3); 

    // Remember to delete the MultiFunc object, or use smart pointers. 
} 

यह आउटपुट:

 
Hello 
3 

दुर्भाग्य से,

आप काम का एक सा भी करने को तैयार कर रहे हैं और हस्ताक्षर की एक सीमित संख्या है, तो आप सिर्फ इस तरह कुछ कर सकते हैं आप टेम्पलेट वर्चुअल फ़ंक्शन नहीं बना सकते हैं या आप इसे आसानी से सामान्यीकृत कर सकते हैं।

2

शायद आप std::map का उपयोग नहीं कर सकते क्योंकि यह एक समरूप कंटेनर है। प्रयास करें, या boost::variant की तरह कुछ (वे आगंतुक पैटर्न का समर्थन) boost::tuple

+0

बढ़ावा :: संस्करण यहां जाने का तरीका है। मैंने इसे कोड में किया है और यह बहुत अच्छा काम करता है। कुछ पंक्तियों (एमपीएल के) में मैं int, float, double, स्ट्रिंग और उन सभी प्रकार के फ़ंक्शन 0 के मानचित्र का समर्थन करता हूं। –

0

दुकान इंटरफेस स्टोर करने के लिए के बारे में बात:

struct IStringData 
{ 
    virtual std::string get() const = 0; 
    virtual ~IStringData() {} 
}; 

और implementaions बनाने के लिए, एक बस स्ट्रिंग मान का आयोजन करेगा, अन्य कार्यान्वयन मज़ेदार स्टोर करेगा, शायद आपके पास भविष्य में अन्य कार्यान्वयन होंगे।

0

नहीं। आप नहीं कर सकते। चूंकि boost :: function polymorphic नहीं है, यह वहां टूट जाता है। (यह तर्क प्रकारों का एक निश्चित सेट लेता है।)

बूस्ट मेल-सूची पर उस दिशा में काम के बारे में बात की गई थी, हालांकि, अभिलेखागार की खोज करें और देखें कि क्या कोई कोड है जिसे आप कर सकते हैं।

बूस्ट :: फ़ंक्शन का उपयोग करने के लिए एक वर्कअराउंड होगा लेकिन फिर आपको मानचित्र में जोड़ने की ज़रूरत है, न कि आपके असली फ़ंक्शन (यानी func1/func2), लेकिन किसी भी कंटेनर से प्रकार को निकालने वाले कार्यों को प्रेषित करें और वास्तविक फ़ंक्शन को कॉल करें । (और यदि यह गलत है, तो यह किसी भी गतिशील लापरवाही में है।)

2

जो आप करने की कोशिश कर रहे हैं वह थोड़ा अजीब लगता है। आम तौर पर, आपके पास एक कंटेनर एक ही हस्ताक्षर वाले सार प्रकार या वस्तुओं या कार्यों का संग्रह होगा। अन्यथा, जब आप कंटेनर को फिर से चालू कर रहे हों तो फ़ंक्शन को कॉल करने के तरीके के बारे में आप कैसे जानेंगे? मैं कंटेनर को एक ज्ञात हस्ताक्षर के साथ फ़ंक्शन ऑब्जेक्ट्स का संग्रह बनाना पसंद करता हूं, फिर बूस्ट का उपयोग करें। अतिरिक्त तर्कों के साथ फ़ंक्शन को कॉल करने के लिए बंद करें।

उदाहरण के लिए:

typedef boost::function<void, void> Function; 
typedef std::map<std::string, Function> Functions; 

Functions functions: 

void foo() 
{ 
    ... 
} 

functions["foo"] = foo; 

void bar(std::string &s) 
{ 
    ... 
} 

// binds the value "hello" to the s parameter 
functions["bar"] = boost::bind(bar, "hello"); 
संबंधित मुद्दे