2012-07-03 15 views
16

मैं std::is_enum को लागू करने की कोशिश कर रहा हूं। यहां मेरा कोड अब तक है:is_enum कार्यान्वयन

template<typename T> 
struct is_enum { 
    static bool value; 
}; 

template<typename T> 
bool is_enum<T>::value = false; 

template<enum E> 
struct is_enum { 
    static bool value; 
}; 

template<enum E> 
bool is_enum<E>::value = true; 

यह कोड त्रुटि का कारण बनता है। अधिक सटीक:

g++ -std=c++0x -Wall -o "enum2" "enum2.cpp" (in directory: /home/aristophanes/Desktop/C++) 
Compilation failed. 
enum2.cpp:11:15: error: use of enum ‘E’ without previous declaration 
enum2.cpp:3:10: error: template parameter ‘class T’ 
enum2.cpp:12:8: error: redeclared here as ‘int E’ 
enum2.cpp:16:15: error: use of enum ‘E’ without previous declaration 
enum2.cpp:17:14: error: ‘E’ was not declared in this scope 
enum2.cpp:17:15: error: template argument 1 is invalid 
enum2.cpp:17:18: error: template declaration of ‘bool value’ 

क्या कोई मुझे बता सकता है कि मैं गलती करता हूं? यह मेरा या संकलक की गलती है? अग्रिम में धन्यवाद।

संपादित करें: यदि यह पूरी तरह गलत है, तो मैं इसे कैसे ठीक कर सकता हूं?

नोट: मैं g++ -o <file> <file>.cpp

+11

मैं काफी हद तक निश्चित हूं कि 'is_enum', कई अन्य प्रकार के गुणों की तरह, संकलक इंट्रिनिक्स के बिना लागू नहीं किया जा सकता है। – ildjarn

+0

[ओटी] इस मामले में, स्थैतिक चर के लिए एक बेहतर विकल्प _enums_ हो सकता है (जैसे: 'enum {value = false};') – Gigi

+5

@Gigi: इसे टैग किया गया है 'C++ 11' - _best_ विकल्प है 'std :: true_type',' std :: false_type', या 'std :: integral_constant <>' से प्राप्त होता है। : -] – ildjarn

उत्तर

13

इसे लागू करने का सबसे अच्छा तरीका कंपाइलर जादू का उपयोग करना है, और मेरा मानना ​​है कि अधिकांश कार्यान्वयन यह करते हैं।

उदाहरण के लिए, यहाँ libC++ के जीसीसी के लिए कार्यान्वयन है> = 4.3 और किसी भी संकलक कि __has_feature(is_enum)

template <class _Tp> struct _LIBCPP_VISIBLE is_enum 
    : public integral_constant<bool, __is_enum(_Tp)> {}; 



सभी अन्य compilers के लिए libC++ करता है:

template <class _Tp> struct _LIBCPP_VISIBLE is_enum 
    : public integral_constant<bool, !is_void<_Tp>::value    && 
            !is_integral<_Tp>::value   && 
            !is_floating_point<_Tp>::value && 
            !is_array<_Tp>::value   && 
            !is_pointer<_Tp>::value   && 
            !is_reference<_Tp>::value  && 
            !is_member_pointer<_Tp>::value && 
            !is_union<_Tp>::value   && 
            !is_class<_Tp>::value   && 
            !is_function<_Tp>::value   > {}; 

में से कुछ उन अन्य प्रकार के लक्षणों को अभी भी कंपाइलर जादू की आवश्यकता है। E.g. is_union। हालांकि, उस शर्त को फिर से लिखा जा सकता है कि इसे कंपाइलर जादू की आवश्यकता नहीं है। यह जोहान्स शैब बताते हैं, दोनों के लिए एक ही चेक के साथ यूनियनों और कक्षाओं के लिए पृथक चेक को प्रतिस्थापित करके किया जा सकता है।

1. जहां तक ​​मुझे पता है कि केवल clang लागू करता है __has_feature दुर्भाग्य से।
2. यह दिलचस्प है कि libC++ में is_union<T> और is_class<T> का संस्करण है जो कंपाइलर इंट्रिनिक्स का उपयोग नहीं करते हैं, लेकिन नतीजतन वे संघ प्रकारों के लिए गलत परिणाम प्रदान करते हैं। लेकिन उनके गलत परिणाम पूरक हैं इसलिए is_enum<T> के libC++ के फ़ॉलबैक कार्यान्वयन सटीक परिणाम प्रदान करता है।

+2

आपका उत्तर गलत है। वैकल्पिक परिभाषा में, आप '! Is_union <_Tp> &&! Is_class <_Tp>' 'is_union_or_class <_Tp>' को प्रतिस्थापित कर सकते हैं, जो एक सदस्य सूचक बनाने और SFINAE पर भरोसा करने के द्वारा संकलक-इंट्रिनिक्स के बिना लागू करने के लिए बहुत सरल है। उल्लिखित सभी अन्य प्रकार के ट्रेनों को आंतरिक सहायता के बिना भी लिखा जा सकता है। –

+0

@ जोहान्सचैब-लीटब अच्छा पकड़ – bames53

+0

@ जोहान्स: आह, 'is_union_or_class' मेरे साथ नहीं हुआ। अच्छी चीज़। – ildjarn

7

यह

template<enum E> 

वादों कि टेम्पलेट तर्क प्रकार enum E के मूल्य है उपयोग कर रहा हूँ। तर्क एक प्रकार नहीं है (टाइप टेम्पलेट तर्क typename, या पिछड़े संगतता के लिए, class द्वारा प्रस्तुत किए गए हैं। यहां तक ​​कि struct की अनुमति नहीं है)। यह

template<int i> 

वैरिएबल के लिए कोई नाम नहीं दिया गया है।

चीजें वहां से गलत हो जाती हैं।

+0

क्या कोड को सही करने का कोई तरीका है? –

+0

@RondogiannisAristophanes: नहीं, आपको एक कंपाइलर बिल्टिन ऑपरेटर की आवश्यकता है, जैसे ildjarn ने टिप्पणियों में कहा। –

1

आप समस्या यह है कि

template<enum E> 

साथ प्रकार आगे घोषित E नामित enum अनाम पैरामीटर के रूप में व्याख्या की है।
शब्दार्थ ही

को
template<int> 

बस enum E साथ int प्रतिस्थापन।

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