2010-10-26 23 views
5

यदि मैं पॉइंटर-टू-बेस-सदस्य बना देता हूं, तो मैं इसे आमतौर पर पॉइंटर-टू-व्युत्पन्न-सदस्य में परिवर्तित कर सकता हूं, लेकिन जब नीचे दिए गए बज़ जैसे टेम्पलेट में उपयोग नहीं किया जाता है, जहां पहला टेम्पलेट तर्क दूसरे को प्रभावित करता है। क्या मैं कंपाइलर कीड़े से लड़ रहा हूं या क्या मानक वास्तव में यह काम नहीं करता है?टेम्पलेट तर्कों में सदस्यों को पॉइंटर को डाउनकास्ट क्यों नहीं कर सकता?

struct Foo 
{ 
    int x; 
}; 

struct Bar : public Foo 
{ 
}; 

template<class T, int T::* z> 
struct Buzz 
{ 
}; 

static int Bar::* const workaround = &Foo::x; 

int main() 
{ 
    // This works. Downcasting of pointer to members in general is fine. 
    int Bar::* y = &Foo::x; 

    // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not? 
    // Error: could not convert template argument '&Foo::x' to 'int Bar::*' 
    Buzz<Bar, &Foo::x> test; 

    // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in 
    // a constant expression 
    Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test; 

    // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot 
    // appear in a constant expression" 
    Buzz<Bar, workaround> test; 

    return 0; 
} 

उत्तर

5

यह बस अनुमति नहीं है। §14.3.2/5:

निम्न रूपांतरण गैर-प्रकार टेम्पलेट-तर्क के रूप में उपयोग की जाने वाली प्रत्येक अभिव्यक्ति पर किए जाते हैं। यदि एक गैर-प्रकार का टेम्पलेट-तर्क संबंधित टेम्पलेट-पैरामीटर के प्रकार में परिवर्तित नहीं किया जा सकता है तो प्रोग्राम खराब बना हुआ है।
- अभिन्न या गणना प्रकार के गैर-प्रकार टेम्पलेट-पैरामीटर के लिए, अभिन्न प्रचार (4.5) और अभिन्न रूपांतरण (4.7) लागू होते हैं।
- ऑब्जेक्ट के लिए प्रकार सूचक के गैर-प्रकार टेम्पलेट-पैरामीटर के लिए, योग्यता रूपांतरण (4.4) और सरणी-से-पॉइंटर रूपांतरण (4.2) लागू होते हैं। - ऑब्जेक्ट के संदर्भ के प्रकार के गैर-प्रकार के टेम्पलेट-पैरामीटर के लिए, कोई रूपांतरण लागू नहीं होता है। संदर्भ द्वारा संदर्भित प्रकार टेम्पलेट तर्क के (अन्यथा समान) प्रकार से अधिक सीवी-योग्य हो सकता है। टेम्पलेट-पैरामीटर सीधे टेम्पलेट-तर्क से बंधे हैं, जो एक अंतराल होना चाहिए।
- कार्य करने के लिए प्रकार सूचक के गैर-प्रकार टेम्पलेट-पैरामीटर के लिए, केवल फ़ंक्शन-टू-पॉइंटर रूपांतरण (4.3) लागू होता है। यदि टेम्पलेट-तर्क ओवरलोडेड फ़ंक्शंस (या ऐसे पॉइंटर) के सेट का प्रतिनिधित्व करता है, तो मिलान फ़ंक्शन सेट (13.4) से चुना जाता है।
- कार्य के संदर्भ के प्रकार के गैर-प्रकार के टेम्पलेट-पैरामीटर के लिए, कोई रूपांतरण लागू नहीं होता है। यदि टेम्पलेट-तर्क ओवरलोडेड फ़ंक्शंस के सेट का प्रतिनिधित्व करता है, तो मिलान फ़ंक्शन सेट (13.4) से चुना जाता है।
- सदस्य फ़ंक्शन के लिए प्रकार सूचक के गैर-प्रकार के टेम्पलेट-पैरामीटर के लिए, कोई रूपांतरण लागू नहीं होता है। यदि टेम्पलेट-तर्क ओवरलोडेड सदस्य फ़ंक्शंस के सेट का प्रतिनिधित्व करता है, तो मेलिंग सदस्य फ़ंक्शन सेट (13.4) से चुना जाता है।
- डेटा सदस्य को टाइप पॉइंटर के गैर-प्रकार के टेम्पलेट-पैरामीटर के लिए, योग्यता रूपांतरण (4.4) लागू होते हैं।

मैंने डेटा सदस्यों को पॉइंटर के संबंध में रूपांतरण पर जोर दिया है। ध्यान दें कि आपका रूपांतरण (§4.11/2) सूचीबद्ध नहीं है। सी ++ 0x में, यह इस संबंध में वही रहता है।

+0

निश्चित रूप से सही है, लेकिन किसी भी विचार की अनुमति क्यों नहीं है? मनमाना लगता है। –

+1

@ जोसेफ: मैंने सोचा कि यह भी किया है, यही कारण है कि मैंने सी ++ 0x भी चेक किया। (उन्होंने फ़ंक्शन टेम्पलेट्स के लिए कोई डिफ़ॉल्ट टेम्पलेट पैरामीटर की तरह कई प्रतीत होता है कि मनमाने ढंग से निर्णय नहीं हटाए गए हैं।) या तो किसी के लिए इसका कोई उपयोग नहीं मिला है और इसलिए यह वास्तव में नहीं बदला गया है/इसलिए इसे आसानी से धक्का नहीं दिया गया था (यह एक अच्छी तरह से जोड़ने के लिए आसान है- एक टूटी हुई सुविधा को कम करने की तुलना में परीक्षण की सुविधा), या कुछ मौलिक कारण है जो मैं नहीं देख सकता। – GManNickG