2013-05-06 7 views
5

मेरे पास एक साधारण वर्ग A है, जो एक विविध कार्य टेम्पलेट प्रदान करता है। यह फ़ंक्शन A के भीतर से निजी डेटा का उपयोग करता है, लेकिन फ़ंक्शन स्वयं सार्वजनिक है।परिवर्तक फ़ंक्शन टेम्पलेट के लिए सूचक

int main(int argc, char *argv[]) {  
    A a; 
    a.bar(1, "two", 3, 4); 
    foo(&a.bar); 
} 
:

class A { 
public: 

    A() : 
    _bla("bla: ") { 
    } 

    template <class T> 
    void bar(const T& value) { 
     std::cout << _bla << value << std::endl; 
    } 

    template <class H, class... T> 
    void bar(const H& value, const T&... data) { 
     std::cout << _bla << value << std::endl; 
     bar(data...); 
    } 

private: 
    const std::string _bla; 
}; 

एक अलग फाइल में, foo.hpp नाम है, मैं एक समारोह foo(), कि प्राप्त करते हैं और एक तर्क के रूप समारोह a.bar() उपयोग करने में सक्षम होना चाहिए: वर्ग इस प्रकार है

मुझे यह सुनिश्चित नहीं है कि कहां से शुरू करना है, लेकिन मैंने निम्नलिखित की कोशिश की है - जो काम नहीं करता है। मैं कैसे इसे सही ढंग से कर सकते हैं:

template <typename... T> 
inline void foo(void (bar *)(const T&...)) { 
    unsigned int x(0), y(0), z(0); 
    bar(x, y, z); 
} 

बोनस सवाल:

foo(&a.bar); 

लेकिन यह भी a.bar कुछ मानकों करने के लिए बाध्य के साथ foo कहते हैं, जैसे:

वहाँ एक रास्ता न केवल कॉल करने के लिए है
foo(&(a.bar(p1, p2)); 

मैं बस p1 और p2 सेजोड़ सकता हूं 10 परिभाषा ही है, में की तरह:

foo(p1, p2, &a.bar); 

लेकिन यह शब्दार्थ मेरा उद्देश्य के लिए बेहतर होगा अगर मैं इन मानकों से पहले जोड़ सकते हैं।

+1

'enable_if' गड़बड़ क्यों? आप इसे 'शून्य बार() {} 'के रूप में अधिभारित कर सकते हैं। – jrok

+1

वैसे, यह तर्क देने के लिए 'enable_if' का उपयोग करने की आवश्यकता नहीं है कि तर्क पैक खाली है या नहीं। '(एच, टी ...) 'के लिए बस एक टेम्पलेट अधिभार है और कोई भी अधिभार नहीं है जो कुछ भी नहीं करता है। –

+0

'foo' फ़ंक्शन स्वीकार करता है, लेकिन 'a.bar' कोई फ़ंक्शन नहीं है। यह एक टेम्पलेट है। टेम्पलेट्स के पास कोई पता नहीं है। कार्य 'a.bar ',' a.bar 'आदि हैं; आप किसको 'foo' पास करना चाहते हैं? साथ ही, आप कुछ पैरामीटर और 'a.bar (p1, p2)' के फ़ंक्शन के रूप में 'a.bar (p1, p2)' को किसी फ़ंक्शन के रूप में अलग-अलग पैरामीटर पर पूरी तरह से लागू करने के तरीके के रूप में कैसे अंतर करते हैं? –

उत्तर

8

आप बिना किसी फ़ंक्शन टेम्पलेट के पते को पास कर सकते हैं, क्योंकि इसे पूरे अधिभार सेट के रूप में माना जाता है (इससे कोई फर्क नहीं पड़ता कि टेम्पलेट भिन्न है या नहीं)। हालांकि, आप यह एक सामान्य functor में लपेट कर सकते हैं:

struct bar_caller 
{ 
    template<typename... Ts> 
    void operator() (A& a, Ts&&... args) 
    { 
     a.bar(std::forward<Ts>(args)...); 
    } 
}; 

और फिर अपने समारोह foo() इस प्रकार परिभाषित किया जा करते हैं:

template<typename F> 
inline void foo(A& a, F f) { 
    unsigned int x(0), y(0), z(0); 
    f(a, x, y, z); 
} 

तो main() में अपने समारोह कॉल बन जाएगा:

int main() 
{ 
    A a; 
    a.bar(1, "two", 3, 4); 
    foo(a, bar_caller()); 
} 

दुर्भाग्यवश, इस समय सी ++ में एक अलग वर्ग को परिभाषित किए बिना एक अधिभार में ओवरलोड लोड को आसानी से लपेटने का कोई तरीका नहीं है - जैसा किके लिए ऊपर किया गया है।

संपादित करें:

आप foo() करने के लिए सीधे एक A वस्तु पारित करने के लिए नहीं करना चाहते हैं, तो आप अभी भी अपने bar_caller Encapsulate A ऑब्जेक्ट के संदर्भ (सिर्फ समारोह bar() के नाम से जाना है, जिस पर दे सकते हैं , वस्तु जीवन का ख्याल रखना ताकि आप उस संदर्भ झूलने बनाने नहीं किया जाएगा):

struct bar_caller 
{ 
    bar_caller(A& a_) : a(a_) { } 

    template<typename... Ts> 
    void operator() (Ts&&... args) 
    { 
     a.bar(std::forward<Ts>(args)...); 
    } 

    A& a; 
}; 

फिर आप foll के रूप में foo() और main() पुनर्लेखन सकता है ows:

template<typename F> 
inline void foo(F f) { 
    unsigned int x(0), y(0), z(0); 
    f(x, y, z); 
} 

int main() 
{ 
    A a; 
    a.bar(1, "two", 3, 4); 
    foo(bar_caller(a)); 
} 
+0

+1 एंडी, आपके उत्तर के लिए बहुत बहुत धन्यवाद! वास्तविक मामले में, मेरे पास एक वर्ग है जो अन्य वर्गों को बढ़ाता है, और इसमें 'ए', मेरे कार्यक्रम में एक छोटी कक्षा शामिल है। अगर मैं 'ए' में अपनी बाहरी कक्षा को '# शामिल' करता हूं - जो वास्तव में बाहरी वर्ग में शामिल होता है - मुझे लगता है कि जो गड़बड़ मैं पहले से ही एक महाकाव्य स्पेगेटी बनूंगा ^^ मुझे वास्तव में दिमाग नहीं है * अतिरिक्त पैरामीटर *, मैं उन्हें 'foo' परिभाषा में जोड़ सकता हूं, लेकिन मैं वास्तव में' ए' - मेरे बाहरी वर्ग - 'foo' को पास नहीं करना चाहता हूं। क्या कोई संभावित काम है? – Rubens

+0

@ रूबेन्स: मैंने अंतिम संपादन –

+0

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

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