2009-05-12 19 views
27

में सी ++ एनम के अंतर्निहित प्रकार मैं एनम के काम को समझने के लिए सी ++ मानक का थोड़ा सा पढ़ने की कोशिश कर रहा हूं। मूल रूप से मैंने सोचा था कि वहां वास्तव में और भी कुछ है।सी ++ 0x

एक स्कॉम्ड गणना के लिए, यह स्पष्ट है कि अंतर्निहित प्रकार int है जब तक कि अन्यथा एनम-बेस क्लॉज (यह कोई अभिन्न प्रकार नहीं हो) के साथ निर्दिष्ट किया जाता है।

enum class color { red, green, blue}; // these are int 

unscoped enumerations के लिए, यह अंतर्निहित प्रकार की तरह लगता है किसी भी अभिन्न प्रकार है कि काम करेंगे और यह एक पूर्णांक से भी बड़ा नहीं होगा कि, जब तक यह होने की जरूरत है हो सकता है।

enum color { red, green, blue}; // underlying type may vary 

के बाद से unscoped enumarations के अंतर्निहित प्रकार मानकीकृत नहीं हैं, जो एक के उदाहरण serializing से निपटने का सबसे अच्छा तरीका है? अब तक, int में कनवर्ट करने के बाद मैं int में क्रमबद्ध करने और मेरे enum स्विच को स्विच करते समय स्विच में बदल रहा हूं, लेकिन यह थोड़ा उलझन में लगता है। क्या कोई बेहतर तरीका है?

enum color { red, green, blue }; 
color c = red; 
// to serialize 
archive << (int)c; 
// to deserialize 
int i; 
archive >> i; 
switch(i) { 
    case 0: c = red; break; 
    case 1: c = green; break; 
    case 2: c = blue; break; 
} 
+2

enum वर्ग है केवल C++ 0x ... – Klaim

+2

+1, यकीन नहीं क्यों इस सवाल -1ed था ... –

+1

संभवतः प्रश्नकर्ता जाहिरा तौर पर एक मौजूदा और प्रस्तावित मानकों दस्तावेज़ के बीच अंतर नहीं कर सकते क्योंकि? –

उत्तर

5

मैंने कोई सी ++ 0x सामान नहीं पढ़ा है, इसलिए मैं उस पर टिप्पणी नहीं कर सका।

सीरियलाइजिंग के लिए, आपको एनम को वापस पढ़ने पर स्विच की आवश्यकता नहीं है - बस इसे enum प्रकार पर डालें।

हालांकि, स्ट्रीम में लिखते समय मुझे नहीं डाला जाता है। ऐसा इसलिए है क्योंकि मैं प्रायः एनम के लिए ऑपरेटर < < लिखना पसंद करता हूं ताकि मैं बुरे मानों को लिखे जा सकूं, या फिर मैं इसके बजाय एक स्ट्रिंग लिखने का निर्णय ले सकता हूं।

enum color { red, green, blue }; 
color c = red; 

// to serialize 
archive << c; // Removed cast 

// to deserialize 
int i; 
archive >> i; 
c = (color)i; // Removed switch 
+1

ऑपरेटर लिखने के विचार के लिए धन्यवाद << enum के लिए। मुझे अपने बारे में सोचना चाहिए था। – criddell

+0

आपकी टिप्पणी में, आपने एक ऑपरेटर लिखने का उल्लेख किया है << और मैं समझता हूं कि उपरोक्त आपका कोड उस ओवरलोड के साथ सही तरीके से काम करेगा। हालांकि, अगर << ओवरलोड नहीं किया गया था, तो किसी को क्रमबद्ध करने से पहले एक int को सी करना चाहिए, सही? – criddell

+0

नहीं, मैं int में नहीं डालागा क्योंकि अगर आपने ऐसा किया और फिर enum ऑपरेटर जोड़ा << बाद में, आपको कोड में सभी जगहें मिलनी होंगी जो कि enum लिखती हैं और कलाकार को हटा देती हैं। – markh44

16

enum वर्ग, एक C++0x सुविधा है यह सी ++ 03 में मौजूद नहीं है।

मानक सी ++ में, गणना प्रकार-सुरक्षित नहीं हैं। वे प्रभावशाली पूर्णांक होते हैं, भले ही गणना प्रकार अलग हैं। यह विभिन्न गणना प्रकारों के दो enum मूल्यों के बीच तुलना की अनुमति देता है। सी ++ 03 प्रदान करने वाली एकमात्र सुरक्षा यह है कि एक पूर्णांक या एक enum प्रकार का मान किसी अन्य enum प्रकार में पूर्ण रूप से परिवर्तित नहीं होता है। इसके अतिरिक्त, अंतर्निहित अभिन्न प्रकार, पूर्णांक का आकार, स्पष्ट रूप से निर्दिष्ट नहीं किया जा सकता है; यह कार्यान्वयन परिभाषित किया गया है। अंत में, गणना मूल्य संलग्न क्षेत्र में डूबे हुए हैं। इस प्रकार, सदस्यों के नाम मिलान करने के लिए दो अलग-अलग गणनाओं के लिए संभव नहीं है। सी ++ 0x गणना के एक विशेष वर्गीकरण की अनुमति देगा जिसमें इनमें से कोई भी समस्या नहीं है। यह (विकिपीडिया लेख से) enum वर्ग घोषणा

उदाहरण का उपयोग करते हुए व्यक्त किया जाता है:

enum Enum1;     //Illegal in C++ and C++0x; no size is explicitly specified. 
enum Enum2 : unsigned int; //Legal in C++0x. 
enum class Enum3;    //Legal in C++0x, because enum class declarations have a default type of "int". 
enum class Enum4: unsigned int; //Legal C++0x. 
enum Enum2 : unsigned short; //Illegal in C++0x, because Enum2 was previously declared with a different type. 

क्रमबद्धता हिस्सा (जो मुझे लगता है कि मूल प्रश्न का हिस्सा नहीं था) के रूप में, मैं करने के लिए पसंद करते हैं एक सहायक वर्ग बनाएं जो enum आइटम्स को उनके स्ट्रिंग समतुल्य (और पीछे) में अनुवाद करता है, क्योंकि नाम आमतौर पर उन पूर्णांक मानों की तुलना में अधिक स्थिर होते हैं, क्योंकि एनम आइटम कोड व्यवहार को बदलने के बिना (और कभी-कभी) पुन: व्यवस्थित किए जा सकते हैं।

1

enum class color के रूप में: क्या यह सी ++/सीएलआई (सी ++ .NET) या भविष्य सी ++ 0x कोड है?

सीरियलाइजेशन के लिए, आप एनम के आकार को sizeof(color) के साथ प्राप्त कर सकते हैं ताकि यह पता चल सके कि कितने बाइट कॉपी करने के लिए हैं।

14

मैंने एक नया जवाब बनाने का फैसला किया क्योंकि मेरा पुराना इतना गन्दा था। वैसे भी बस कुछ के बारे में सी ++ 11, जहां आप इस का उपयोग कर एक गणन के अंतर्निहित प्रकार प्राप्त कर सकते हैं कहना चाहता हूँ:

std::underlying_type_t<E> 

और ब्याज की खातिर, अधिभार संकल्प विचार के लिए। लेकिन कृपया @lothar द्वारा प्रस्तावित गणना को संग्रहीत करने के लिए नामों का उपयोग करें।

ओवरलोड रिज़ॉल्यूशन इस तथ्य से उत्पन्न होता है कि एक गणना से पहले, इंटिनेटेड int, लंबे, हस्ताक्षरित लंबे समय तक एक पदोन्नति मौजूद है जो इसके अंतर्निहित प्रकार के सभी मूल्यों का प्रतिनिधित्व कर सकती है। किसी भी अन्य पूर्णांक प्रकार में रूपांतरण कम रैंकिंग और अधिभार संकल्प इसे पसंद नहीं करेगा।

char (& f(int))[1]; 
char (& f(unsigned int))[2]; 

char (& f(long))[3]; 
char (& f(unsigned long))[4]; 

char const* names[] = { 
    "int", "unsigned int", 
    "long", "unsigned long" 
}; 

enum a { A = INT_MIN }; 
enum b { B = UINT_MAX }; 
enum c { C = LONG_MIN }; 
enum d { D = ULONG_MAX }; 

template<typename T> void print_underlying() { 
    std::cout << names[sizeof(f(T()))-1] << std::endl; 
} 

int main() { 
    print_underlying<a>(); 
    print_underlying<b>(); 
    print_underlying<c>(); 
    print_underlying<d>(); 
} 

और यह इस एक यहाँ प्रिंट:

int 
unsigned int 
int 
unsigned int 

यह (के बाद से डेटा धारावाहिक का आकार लगातार चौड़ाई का नहीं है इस क्रमबद्धता समस्या के लिए विशेष रुचि का नहीं है, और इस समस्या है जब पैदा कर सकता है गणना और इसके अंतर्निहित प्रकार को बदल दिया गया है), लेकिन यह आमतौर पर एक गणना को संग्रहीत करने के प्रकार को समझना दिलचस्प होता है। चीयर्स!

+0

'std :: underlying_type' सही प्रकार प्राप्त करने का सबसे अच्छा समाधान है। बस एक छोटा सुधार: सहायक ** 'std :: underlying_type_t ' ** ** सी ++ 14 ** के माध्यम से उपलब्ध है; ** सी ++ 11 ** के लिए आपको ** 'std :: underlying_type :: इसके बजाय टाइप ** ** का उपयोग करना होगा। – ollo

5
#include <type_traits> 

enum a { bla1, bla2 }; 
typedef typename std::underlying_type<a>::type underlying_type; 

if (std::is_same<underlying_type, int>::value) 
    std::cout << "It's an int!" << endl; 
else if (std::is_same<underlying_type, unsigned int>::value) 
    std::cout << "It's an uint!" << endl; 
+2

वास्तव में कोड का एक ब्लॉक regurgitating करने के बजाय, कुछ क्या कर रहा है, यह बताने के लिए पाठ का उपयोग करने के लिए यह परंपरागत है। –

+0

मैं एक स्पष्टीकरण पर एक स्टैब ले जाऊंगा। कोड इंटीरियर के अंतर्निहित प्रकार को समझने के लिए संकलक प्राप्त करने के लिए थोड़ा सा टेम्पलेट जादू का उपयोग कर रहा है। मैंने पूछा था कि धारावाहिक उद्देश्यों के लिए अंतर्निहित प्रकार को कैसे समझें और कोड का यह बिट ऐसा करेगा। – criddell