2011-12-06 10 views
6

मैं निम्नलिखित टेम्पलेट वर्ग और एक (वैश्विक) अपनी तरह का चर:का पता लगा रहा एक प्रकार सी में से प्राप्त किया जा सकता है अगर ++

template <typename ClassT> 
struct ClassTester : public ClassT { 
    typedef ClassT type; 
}; 

ClassTester<int> *aaa; // No error here 

मैं एक संकलन त्रुटि उम्मीद होती है क्योंकि int से प्राप्त नहीं किया जा सकता है, लेकिन इस विज़ुअल सी के तहत ठीक संकलित ++ 2010

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

ClassTester<int> bbb; // Error here 

मैं w कि क्या दिया प्रकार एक वर्ग है कि से प्राप्त किया जा सकता है SFINAE परीक्षण के लिए इस वर्ग का उपयोग करने के anted:

template <typename T> 
struct CanBeDerivedFrom { 

    template <typename C> 
    static int test(ClassTester<T> *) { } 

    template <typename> 
    static char test(...) { } 

    static const bool value = (sizeof(test<T>(0)) == sizeof(int)); 
}; 

लेकिन यह हमेशा सच रिपोर्ट करती है, यहां तक ​​कि इसके बाद के संस्करण कारण की वजह से इस तरह के int के रूप में आदिम प्रकार के लिए। क्या यह सी ++ का अपेक्षित/वैध व्यवहार है?

+1

मुझे संदेह है कि एक पॉइंटर को घोषित करने/परिभाषित करने के लिए वास्तव में टेम्पलेट को तुरंत चालू करने की आवश्यकता नहीं होती है। आखिरकार, आप किसी भी चीज़ के लिए 'क्लासटेस्टर *' का उपयोग नहीं करते हैं। – visitor

+0

एक समान उदाहरण यह जांच करेगा कि टेम्पलेट पैरामीटर पीओडी या गैर पीओडी है या नहीं। –

+0

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

उत्तर

1

मुझे लगता है कि यह संभव नहीं है पूरी तरह से class प्राप्त करने के लिए जो SFINAE के माध्यम से व्युत्पन्न है (जिसमें सी ++ 11 में final class के मामले भी शामिल हैं)। सबसे अच्छी चीज जो किया जा सकता है वह यह है कि कोई प्रकार class है या उस पर भरोसा करता है, तो यह जानने के लिए एक SFINAE है।यदि दिए गए प्रकार class/union है या नहीं

template<typename T> 
struct void_ { typedef void type; }; 

template<typename T, typename = void> 
struct CanBeDerivedFrom { 
    static const bool value = false; 
}; 

template<typename T> 
struct CanBeDerivedFrom<T, typename void_<int T::*>::type> { 
    static const bool value = true; 
}; 

यह metaprogram मिल जाएगा। demo

+1

भले ही यह 100% उत्तर नहीं है, यह निश्चित रूप से एक दिलचस्प दृष्टिकोण है। –

0

आप आरटीटीआई (रन टाइम टाइप जानकारी) का उपयोग यह जानने के लिए कर सकते हैं कि कक्षा किस प्रकार से संबंधित है, और यदि वर्ग मूल प्रकार का है तो आप बता सकते हैं कि कक्षा से नहीं लिया जा सकता है।

पूर्व: अगर (typeid (टी) == typeid (int) || typeid (टी) == typeid (नाव)) { < < अदालत "वर्ग से प्राप्त नहीं किया जा सकता"; }

आप अगर हालत

+0

आपके उत्तर के लिए धन्यवाद लेकिन मुझे इसे संकलित समय पर, रनटाइम पर नहीं चाहिए। –

4

करने के लिए यदि आप चाहते हैं अधिक प्रकार जोड़ सकते हैं, पहिया बदलने मत करो। बूस्ट का उपयोग करें :: is_class boost reference manual

वे लोग आपके से बेहतर जानते हैं।

+2

boost :: is_class थोड़ा अलग काम करता है - यह परीक्षण करता है कि दिया गया प्रकार एक वर्ग है या नहीं। मैं यह जांचना चाहता हूं कि किस प्रकार से प्राप्त किया जा सकता है। ये दो नए सी ++ 11 मानक में समान नहीं हैं। और मुझे कोई बूस्ट प्रकार की विशेषता नहीं मिली है जो मुझे इसे प्राप्त करने में मदद करेगी। –

+2

यह उत्तर बहुत कठोर है। – iammilind

+0

मुझे नहीं लगता कि वह इसके लिए कठोर होना था। हेस ने कहा कि बूस्ट ने थोड़ी देर के लिए इस तरह की चीज में अपना शोध किया है, इसलिए आप बूस्ट का उपयोग करके बेहतर हैं: is_class या कम से कम इसे कैसे लागू किया गया था इसे देखें। – Jeremy

1

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

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

+0

यदि मैं पॉइंटर तक पहुंचने का प्रयास करता हूं तो यह एक कंपाइलर त्रुटि देता है कि कक्षा int से प्राप्त नहीं हो सकती है। यह भी अजीब बात है, मैंने सोचा कि SFINAE केवल उस अधिभार को अस्वीकार कर देगा और एक त्रुटि फेंक नहीं देगा। –

0
#include <typeinfo> 

main() 
{ 
int i; 
int * pi; 
cout << int is: << typeid(int).name() << endl; 
cout << i is: << typeid(i).name() << endl; 
cout << pi is: << typeid(pi).name() << endl; 
cout << *pi is: << typeid(*pi).name() << endl << endl; 

}

यह प्रिंट:

 

int 
int 
int* 
int 

अपेक्षा के अनुरूप ..

किसी अन्य पुस्तकालय के स्वतंत्र होने की जरूरत है ... इसलिए पुस्तकालय को बढ़ावा देने के लिए यह एक अच्छा जवाब नहीं है ..

2

दुर्भाग्य से मुझे लगता है कि यह वास्तव में असंभव है।

कई मुद्दे व्युत्पन्न (या कम से कम, उपयोगी व्युत्पन्न) को रोक सकते हैं, मानक के लिए final के अतिरिक्त।

उदाहरण के लिए, क्लैंग मेलिंग सूची पर this thread देखें जहां हॉवर्ड हिन्नेंट को यह जांचने के लिए एक कंपाइलर आंतरिक की आवश्यकता होती है कि कक्षा final के रूप में चिह्नित है या नहीं।

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

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