2011-11-09 14 views
10

की संख्या के बराबर बिस्ट प्लेसहोल्डर तर्क को बढ़ावा देना मैं जानना चाहता हूं कि एक बूस्ट :: बाइंड कॉल में प्लेसहोल्डर के रूप में एक विविध टेम्पलेट में पारित तर्कों की संख्या का उपयोग करना संभव है या नहीं।विविधता टेम्पलेट तर्क

कुछ इस तरह:

template <typename ... Args> 

boost::bind(&function, this, anArg, _1));   //If Args count equals 1 
boost::bind(&function, this, anArg, _1, _2));  //If Args count equals 2 
boost::bind(&function, this, anArg, _1, _2, _3)); //If Args count equals 3 

यह संभव है?

धन्यवाद

+4

यहां मेक_इंडिस उपयोगिता का एक अच्छा कार्यान्वयन है: [http://preney.ca] (http://preney.ca/paul/2011/10/16/applying-stdtuple-to-functors- कुशलतापूर्वक /) लेकिन मुझे यह समझने में कठिनाई हो रही है कि मैं इसे बढ़ावा देने के साथ कैसे उपयोग कर सकता हूं :: arg Blizter

+0

वह लिंक एक महान पढ़ा गया था, और 'लागू (Func, std :: tuple)' फ़ंक्शन किसी दिन काम में आ सकता है । –

+0

मैं 'टाइपनाम ... Args' देखता हूं। क्या आप सी ++ 11 का उपयोग कर रहे हैं? – kennytm

उत्तर

1

वहाँ निश्चित रूप से आंशिक विशेषज्ञता के साथ एक तरीका है: तुम सिर्फ एक समाधान तीन अलग-अलग हस्ताक्षर जो उनके पैरामीटर प्रकार से भिन्न होते हैं संभाल करने के लिए देख रहे हैं, तो आप ऐसा ही कुछ कर सकता है। आपकी वैरिएडिक तुरंत तर्कों की संख्या को नहीं जानता है? आपको संकलन-समय रिकर्सन का उपयोग करना होगा, इस समय आप बूस्ट :: एमपीएल (या एक साधारण अभिन्न निरंतर वृद्धि का उपयोग करके उन्हें गिनें) का उपयोग करके अपने तर्कों को ढेर कर सकते हैं। फिर आपके अंतिम गैर-वैरिएडिक रिकर्सन कॉल (0 arg के साथ) में आप अपने कंटेनर पर mpl :: आकार को कॉल करते हैं (या अगर आपने इसे चुना है तो अभिन्न काउंटर का उपयोग करें) दूसरे उत्तर की तरह कॉल करने योग्य कॉल करने के लिए, जो सभी को भालू तर्क सूची, प्लस सूची की शुरुआत में एक अभिन्न टेम्पलेट पैरामीटर। और यही वह है जिसे आप विशेषज्ञ करते हैं। आप प्रत्येक तर्क के लिए एक कॉलर बनाते हैं जो तर्कसंगत तर्कों के अनुसार सही बाध्य को कॉल करेगा। (कॉल करने योग्य संरचनाएं (आंशिक रूप से) तर्क अभिन्न टेम्पलेट पैरामीटर की संख्या के अनुसार विशिष्ट हैं। और भले ही कॉल फ़ंक्शन अधिकतम संख्या में तर्क लेता है, फिर भी यह केवल सही बूस्ट :: बाइंड कॉल को लपेटता है उदाहरण के लिए बाइंड (.. , _1, _2) कॉल करने योग्य < 2, टी 1, टी 2, टी 3>) यह भयानक नहीं है, लेकिन मैं पुष्टि करता हूं कि मैंने अतीत में सी ++ 03 में इस दृष्टिकोण का उपयोग किया है।

0

हो सकता है कि आप क्या आप थोड़ा और अधिक विस्तार से क्या करना चाहते हैं की व्याख्या करनी चाहिए।

template<typename signature> 
struct callable; 

template<typename P0, typename P1, typename P2> 
struct callable<void (P0, P1, P2)> 
{ 
    void bind() 
    { 
     boost::bind(&callable::operator(), this, _1, _2, _3); 
    } 

    void operator()(P0, P1, P2) {} 
}; 
0

यह विशिष्ट समस्या का उत्तर नहीं है, लेकिन समस्या के लिए एक अच्छा कामकाज है जिसे आप हल करने की कोशिश कर रहे हैं।

मैं एक सामान्य प्रतिनिधि तंत्र को लागू करते समय एक ही मुद्दे में भाग गया। मेरा समाधान केवल बाइंड कॉल के शीर्ष पर एक रैपर का उपयोग करना था, जो विविधता के लिए विशेषज्ञता रखते थे। हालांकि यह इस मुद्दे को हल नहीं करता है, यह निश्चित रूप से केवल बाध्य कॉल के लिए अनावश्यक कोड को कम करता है और सबसे महत्वपूर्ण रूप से मुझे एक विविध पैरामीटर आधारित प्रतिनिधि प्रणाली देता है जिसे मैं हर जगह उपयोग कर सकता हूं।

template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE> 
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(), CALLBACK_TARGET_CLASS* callbackTarget) 
{ 
    return std::bind(memberFunction, callbackTarget); 
} 

template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE, typename P0> 
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(P0), CALLBACK_TARGET_CLASS* callbackTarget) 
{ 
    return std::bind(memberFunction, callbackTarget, std::placeholders::_1); 
} 

template<class CALLBACK_TARGET_CLASS, typename RETURN_TYPE, typename P0, typename P1> 
std::function<RETURN_TYPE()> BindFunction(RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(P0, P1), CALLBACK_TARGET_CLASS* callbackTarget) 
{ 
    return std::bind(memberFunction, callbackTarget, std::placeholders::_1, std::placeholders::_2); 
} 



template<typename RETURNTYPE, typename... ARGS> 
struct Delegate 
{ 
    std::function<RETURN_TYPE (ARGS...)> callbackFunction; 

    template<class CALLBACK_TARGET_CLASS> 
    void Bind(CALLBACK_TARGET_CLASS* callbackTarget, RETURN_TYPE (CALLBACK_TARGET_CLASS::*memberFunction)(ARGS...)) 
    { 
     callbackFunction = BindFunction<CALLBACK_TARGET_CLASS, RETURN_TYPE, ARGS...>(memberFunction, callbackTarget); 
    } 

    void Callback(ARGS... params) 
    { 
     callbackFunction(params...); 
    } 
}; 

प्रयोग समाप्त हो जाती है हमें इस तरह देख ..

class Foo 
{ 
public: 
    void Bar(int x); 
} 

Foo foo; 
Delegate<void, int> myDelegate; 

myDelegate.Bind(&foo, &Foo::Bar); 

myDelegate.Callback(3); 
0

का उपयोग _1, _2, ... सीधे variadic टेम्पलेट के साथ संभव नहीं है। आपको इसके बजाय विशाल मैक्रोज़ का उपयोग करने की आवश्यकता है।

हालांकि, आप टेम्पलेट तर्क 1, _2 के लिए 2, आदि के साथ _1 प्राप्त करने के लिए एक टेम्पलेट कारखाने में प्लेसधारकों को लपेट सकते हैं ...इस तरह के जीसीसी/MSVC के रूप में

कार्यान्वयन पहले से ही प्लेसहोल्डर परिभाषित के रूप में टेम्प्लेटेड struct (क्रमशः std :: _ प्लेसहोल्डर और std :: _ पीएचडी) ताकि आप आप कारखाना इस तरह से परिभाषित कर सकते हैं:

struct ph_factory { 
    template<size_t holder> 
    static std::_Placeholder<holder> make_ph() { 
     return std::_Placeholder<holder>(); 
    } 
}; 

यह परिभाषित, आप विस्तार कर सकते हैं सभी प्लेसहोल्डर के साथ एक पैरामीटर पैक आप चाहते हैं:

struct tester { 

    template<size_t ... holders> 
    void test(int val) { 
     auto callable = std::bind(&tester::call, this, val, ph_factory::make_ph<holders>()...); 
     callable('a', 42, 'c'); 
    } 

    void call(int v1, char c1, int v2, char c2) { 
     cout << "calling :" << v1 << " " << c1 << " " << v2 << " " << c2 << endl; 
    } 
}; 

तो निम्न कोड होगा उत्पादन "बुला: 10 सी 42 एक"

int main() { 
    tester t; 
    t.test<3,2,1>(10); 
} 

make_indice जैसे चालों का उपयोग करके आपको मूल लक्ष्य प्राप्त करने की संभावना मिल जाएगी।

+2

कभी भी '_Names' पर भरोसा न करें, वे कार्यान्वयन के लिए पूरी तरह से निजी हैं और आपके पास कभी भी उनके बारे में सोचने का कोई कारण नहीं है। बेहतर तरीके हैं, एक ऐसा है कि आप सभी प्लेसहोल्डर्स को 'टुपल' में डालते हैं और '' पैक पैक के साथ उन्हें प्राप्त करते हैं। दूसरा यह है कि आप अपना खुद का प्लेसहोल्डर पंजीकृत करते हैं (मानक इस कारण से 'is_placeholder' विशेषता प्रदान करता है, जिसे आप विशेषज्ञ बना सकते हैं। – Xeo