2012-01-30 8 views
7

मैं एक स्थिर रूप से बाध्य प्रतिनिधि वर्ग बनाने की कोशिश कर रहा हूं, जहां सदस्य कार्य संकलन समय पर बाध्य है, जिससे अनुकूलन सहायता मिलती है।सदस्य समारोह में सूचक के लिए टेम्पलेट तर्क कटौती?

मैं निम्नलिखित कोड है जो वास्तव में काम करता है मैं इसे कैसे करना चाहते हैं:

#include <iostream> 

namespace thr { 

template<typename T, T func> 
struct delegate; 

template<typename R, 
     typename C, 
     typename... A, 
     R (C::* mem_fun)(A...)> 
struct delegate<R(C::*)(A...), mem_fun> 
{ 
    delegate(C* obj_) 
    : _obj(obj_) 
    {} 

    R operator()(A... a) 
    { 
    return (_obj->*mem_fun)(a...); 
    } 
private: 
    C* _obj; 
}; 

} // namespace thr 

struct foo 
{ 
    double bar(int i, int j) 
    { 
    return (double)i/(double)j; 
    } 
}; 

int main() 
{ 
    foo f; 

    typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;  
    cb c(&f); 

    std::cout << c(4, 3); 
    return 0; 
} 

हालांकि, उपयोग बहुत ही सुंदर नहीं है:

thr::delegate<decltype(&foo::bar), &foo::bar> 

मैं एक समारोह टेम्पलेट का उपयोग करना चाहते हैं जो टेम्पलेट पैरामीटर को कम करता है और एक प्रतिनिधि उदाहरण देता है; के (इस कोड संकलन नहीं करता है) पंक्तियों के साथ कुछ:

template<typename C, typename T, T func> 
thr::delegate<T, func> bind(T func, C* obj) 
{ 
    return thr::delegate<decltype(func), func>(obj); 
} 

यह और अधिक सुरुचिपूर्ण वाक्य रचना के लिए अनुमति होगी:

auto cb = bind(&foo::bar, &f); 

यह एक समारोह टेम्पलेट में एक गैर प्रकार पैरामीटर अनुमान करना संभव है?

क्या मैं भी संभव हासिल करने की कोशिश कर रहा हूं?

+0

कभी-कभी फ़ंक्शन टेम्पलेट में गैर-प्रकार पैरामीटर को कम करना संभव होता है, उदाहरण के लिए 'एन' को' टेम्पलेट size_t int_array_length (int (& array_ref) [N]) {वापसी एन;} 'में घटाया जा सकता है। लेकिन निश्चित रूप से 'एन' एक प्रकार का नहीं होने के बावजूद फ़ंक्शन हस्ताक्षर में एक प्रकार का हिस्सा है। –

+1

एक मैक्रो जोड़ें: '# परिभाषित करें MAKE_DELEGATE (x, y) thr :: प्रतिनिधि (y) 'मैं फ़ंक्शन नामकरण से बचने के लिए कोई और तरीका नहीं देख सकता। –

+0

@Iori: आपको एहसास है कि आपके उदाहरण में, 'टी' 'func' का प्रकार होगा, इसलिए 'decltype' आवश्यक नहीं है :)? –

उत्तर

1

यह एक समारोह हस्ताक्षर में प्रकार के अलावा अन्य संस्थाओं निकालना संभव है, लेकिन समारोह के लिए खुद को फिर टेम्पलेट पैरामीटर के रूप में नहीं किया जा सकता है पैरामीटर।

को देखते हुए:

template <size_t I> struct Integral { static size_t const value = I; }; 

आप हो सकते हैं:

template <size_t N> 
Integral<N> foo(char const (&)[N]); 

लेकिन तुम नहीं कर सकते हैं:

Integral<N> bar(size_t N); 
सरणी के आकार के रूप

पूर्व के मामले में, N हिस्सा है तर्क के प्रकार के बाद, बाद के मामले में, N तर्क है। यह देखा जा सकता है कि पूर्व मामले में, N प्रकार हस्ताक्षर की टेम्पलेट पैरामीटर सूची में दिखाई दिया।

इसलिए, यदि आप वास्तव में जो चाहते हैं, तो सदस्य सूचक मान फ़ंक्शन हस्ताक्षर की टेम्पलेट पैरामीटर सूची के हिस्से के रूप में दिखाई देना होगा।

एक बचत अनुग्रह constexpr का उपयोग, जो टेम्प्लेट पैरामीटर के लिए एक निरंतर फिट में एक नियमित रूप से मूल्य बदल सकते हैं हो सकता है:

constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); } 

Integral<fib(4)> works; 

लेकिन मैं पर्याप्त समझ रखने वाले है कि सड़क के नीचे जाने के लिए नहीं कर रहा हूँ ...

हालांकि मेरे पास एक साधारण सवाल है: आपको क्यों लगता है कि यह चीजों को गति देगा? कंपाइलर निरंतर प्रचार और इनलाइनिंग पर बहुत अच्छे होते हैं, जब वे संकलन में गतिशील प्रकार के चर का आकलन कर सकते हैं तो आभासी कार्यों में कॉल इनलाइन करने में सक्षम होने के बिंदु पर। क्या आप वाकई इस पर पसीना लायक हैं?

4

क्या std :: function help होगा? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function आपका उदाहरण काफी करीब दिखता है।

मुझे लगता है कि एसटीएल की आपूर्ति की गई संकलक इसे आसानी से काम करने के लिए बहुत ही भयानक चीजें करता है। छोड़ने से पहले आप एक उदाहरण के रूप में देखना चाहते हैं।

संपादित करें: मैं बाहर गया और कोशिश करने की कोशिश की कि आप क्या करने की कोशिश कर रहे हैं। मेरा निष्कर्ष एक संकलन त्रुटि है:

  • बाइंड (प्रतिनिधि) के वापसी प्रकार को सूचक को सदस्य का नाम देना चाहिए क्योंकि यह आपकी अपनी आवश्यकता है।
  • bind सदस्य के लिए सूचक के नाम को स्वीकार सुरुचिपूर्ण (अर्थात आपकी आवश्यकता) होने के लिए
  • संकलक की आवश्यकता है एक समारोह पैरामीटर के साथ टेम्पलेट पैरामीटर शैडो नहीं करने के लिए या दोनों मानकों में नाम का उपयोग और वापसी प्रकार करना चाहिए।

इसलिए आपकी आवश्यकताओं में से एक जाना चाहिए।

संपादित करें 2: मैंने आपके प्रतिनिधि को बदलने की स्वतंत्रता ली है, इसलिए आप चाहें कामों को बाध्य करें। बाध्य हालांकि आपकी प्राथमिकता नहीं हो सकती है।

#include <iostream> 

namespace thr { 


template<typename C,typename R,typename... A> 
struct delegate 
{ 
private: 
    C* _obj; 
    R(C::*_f)(A...); 
    public: 
    delegate(C* obj_,R(C::*f)(A...)) 
    : _obj(obj_),_f(f) 
    {} 

    R operator()(A... a) 
    { 
    return (_obj->*_f)(a...); 
    } 

}; 

} // namespace thr 

template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){ 
    return thr::delegate<C,R,A...>(obj,f); 
} 

struct foo 
{ 
    double bar(int i, int j) 
    { 
    return (double)i/(double)j; 
    } 
}; 

int main() 
{ 
    foo f; 
    auto c = bind(&foo::bar, &f); 
    std::cout << c(4, 6); 
    return 0; 
} 
+0

'std :: function 'अपने टेम्पलेट पैरामीटर में केवल प्रकार लेता है, और कोई मान नहीं। –

+0

जैसा कि मैं इसे समझता हूं, इस excersice का बिंदु प्रतिनिधि प्रकार को स्पष्ट रूप से टाइप नहीं करना है। एक 'ऑटो' slapping संभव और पर्याप्त होना चाहिए। – artificialidiot

+0

मुझे ऐसा नहीं लगता है। मुझे लगता है कि लक्ष्य को डुप्लिकेटिंग जानकारी के शीर्ष पर टेम्पलेट पैरामीटर (उदाहरण में) के रूप में पॉइंटर-टू-सदस्य-फ़ंक्शन होना था। –