2012-07-31 31 views
14

यह ज्ञात है कि टेम्पलेट तर्क सदस्य कार्यों के लिए पॉइंटर्स हो सकते हैं।सदस्य फ़ंक्शन पॉइंटर्स के लिए टेम्पलेट तर्क कटौती

तो मैं लिख सकते हैं:

struct Bar 
{ 
    int fun(float x); 
}; 

template <int (Bar::*FUN)(float)> 
struct Foo 
{ /*...*/ }; 

typedef Foo<&Bar::fun> FooBar; 

लेकिन क्या होगा अगर मैं Bar प्रकार अपने आप में एक टेम्पलेट तर्क होना चाहते हैं:

template <typename B, int (B::*FUN)(float)> 
struct Foo 
{ /*...*/ }; 

typedef Foo<Bar, &Bar::fun> FooBar; 

अब, जब मैं इसे इस्तेमाल करते हैं, मैं लिखने के लिए है Bar दो बार!

मेरा प्रश्न है: क्या संकलक को कक्षा प्रकार को स्वचालित रूप से कम करने के लिए मजबूर करने का कोई तरीका है?

उद्देश्य सिर्फ काम करने के लिए इस के लिए है:

typedef Foo<&Bar::fun> FooBar; 
typedef Foo<&Moo::fun> FooMoo; 

उत्तर

5

आपको शायद वहां कक्षा का नाम लिखना चाहिए। हालांकि, अगर आप वास्तव में इससे बचना चाहते हैं तो आप मैक्रोज़ के बुरे जादू का उपयोग कर सकते हैं। सरल संस्करण अधिक खतरनाक है:

#define TT(X) decltype(X), X 

template<typename T,T t> 
struct Foo 
{ /* ... */ }; 

struct Bar { 
    int fun(float) {} 
}; 

int main() { 
    Foo<TT(&Bar::fun)> f; 
} 

इस गैर प्रकार टेम्पलेट पैरामीटर के किसी भी प्रकार को स्वीकार करेंगे, और आपके सामने आने वाले मुश्किल से समझ में त्रुटियों अगर Foo कार्यान्वयन केवल संकेत करने वाली किसी सदस्य के साथ काम करता है।

template<typename T> struct member_ptr_traits; 

template<typename Class,typename Ret,typename... Args> 
struct member_ptr_traits<Ret (Class::*)(Args...)> 
{ 
    typedef Class class_type; 
    typedef Ret return_type; 
}; 

#define TT(X) member_ptr_traits<decltype(X)>::class_type , X 

template<typename T,int (T::*FUN)(float)> 
struct Foo 
{ /* ... */ }; 

struct Bar { 
    int fun(float) {} 
}; 

int main() { 
    Foo<TT(&Bar::fun)> f; 
} 
इसके अलावा इनमें से

दोनों का उपयोग सी ++ 11 तो वे पुराने compilers साथ काम नहीं करेंगे:

यह थोड़ा सुरक्षित आप एक metafunction कि आप वर्ग के नाम बताता है की जरूरत बनाने के लिए। इस सरल संस्करण को पुराने typeof या इसी तरह के कंपाइलर एक्सटेंशन का उपयोग करने के लिए फिर से लिखा जा सकता है। सुरक्षित संस्करण को पुनर्लेखन करने के लिए विविधतापूर्ण टेम्पलेट्स को अनुकरण करने की आवश्यकता होती है।

+0

अंतर्दृष्टि के लिए धन्यवाद, असल में, मैं इसके लिए बदसूरत मैक्रोज़ का उपयोग कर रहा हूं (यह एक पुस्तकालय के लिए एक टेम्पलेट आंतरिक है, इसलिए दुरुपयोग का कोई वास्तविक खतरा नहीं है)। वैसे भी, 'member_ptr_traits' बहुत अच्छा है क्योंकि मुझे वास्तव में 'टी' प्रकार की आवश्यकता है। – rodrigo

7

सरल जवाब: कोई वहाँ नहीं है।

समस्या यह है कि typedef Foo<&Bar::fun> FooBar; काम करने के लिए, टेम्पलेट में एक गैर-प्रकार का तर्क होना होगा, लेकिन उस तर्क का प्रकार अज्ञात होगा जब टेम्पलेट घोषित किया जा रहा है, जो मान्य नहीं है। दूसरी तरफ, कटौती का प्रकार कभी भी टेम्पलेट के तर्कों पर लागू नहीं होता है (केवल टेम्पलेट्स को फ़ंक्शन करने के लिए तर्कों के लिए, लेकिन वे फ़ंक्शन के लिए तर्क हैं, टेम्पलेट नहीं)।

+0

समझा। इसलिए टेम्पलेट फ़ंक्शन के लिए भी असंभव होगा, है ना? – rodrigo

+0

@rodrigo: यदि आप उस टेम्पलेट तर्क को पॉइंटर-टू-सदस्य हां के रूप में लेना चाहते हैं। सवाल यह है कि क्या आपको सदस्य को टेम्पलेट तर्क होने के लिए सूचक की आवश्यकता है, या यह एक फ़ंक्शन तर्क हो सकता है, जिसे घटाया जा सकता है। –

+0

हां, मुझे इसे टेम्पलेट तर्क होने की आवश्यकता है क्योंकि इसे किसी नेस्टेड टेम्पलेट को तुरंत चालू करने के लिए उपयोग किया जाना चाहिए। वैसे भी, – rodrigo

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