2012-02-26 11 views
20

मैं कुछ राज्य मशीन है कि मैं कर रहा हूँ को लागू करने में राज्यों की गणना करने में एक दायरे वाला enum उपयोग कर रहा हूँ।स्कॉप्ड गणनाओं के लिए "नेमस्पेस एक्स का उपयोग" के समतुल्य?

enum class CatState 
{ 
    sleeping, 
    napping, 
    resting 
}; 

मेरी cpp फ़ाइल में जहां मैं एक राज्य संक्रमण तालिका परिभाषित करते हैं, मैं using namespace X के लिए कुछ बराबर उपयोग करने के लिए इतना है कि मैं के साथ सभी मेरे राज्य के नाम उपसर्ग की जरूरत नहीं है चाहते हैं: उदाहरण के लिए, मान लीजिए कि कुछ पसंद करते हैं CatState::। दूसरे शब्दों में, मैं sleeping बजाय CatState::sleeping उपयोग करना चाहते हैं। मेरी संक्रमण तालिका में कुछ कॉलम हैं, इसलिए CatState:: उपसर्ग से परहेज करना चीजों को अधिक कॉम्पैक्ट और पठनीय रखेगा।

तो, वहाँ एक रास्ता CatState:: हर समय टाइप करने के लिए होने से बचने के लिए है?


हाँ, हाँ, मैं पहले से ही using namespace के नुकसान के बारे में पता कर रहा हूँ। यदि दृढ़ता से टाइप किए गए enums के बराबर है, तो मैं केवल अपने सीपीपी कार्यान्वयन फ़ाइल में सीमित दायरे के अंदर इसका उपयोग करने का वादा करता हूं, न कि बुराई के लिए।

+0

क्या आपको वास्तव में 'एनम क्लास' की आवश्यकता है, या एक 'enum' करना होगा? – netcoder

+0

यह मूल रूप से एक सादा 'enum' था, लेकिन मैं C++ 11 सुविधाओं का उपयोग करने के लिए अपना कोड बदल रहा हूं। मुझे 'एनम क्लास' के साथ मजबूत प्रकार की सुरक्षा का विचार पसंद है। –

उत्तर

11

तो, क्या हर समय CatState:: टाइप करने से बचने का कोई तरीका है?

नहीं। जैसे स्थिर वर्ग सदस्यों के लिए ClassName:: टाइप करने के लिए कोई समकक्ष नहीं है। आप using typename ClassName नहीं कह सकते हैं और फिर आंतरिक पर पहुंच सकते हैं। दृढ़ता से enum एस टाइप करने के लिए भी यही है।

आप निश्चित रूप से नियमित enum एस का उपयोग करके enum class वाक्यविन्यास का उपयोग नहीं कर सकते हैं। लेकिन फिर आप मजबूत टाइपिंग खो देते हैं।

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

+1

+1 धन्यवाद। मैं मजबूत नाम को कल्पना कर रहा था कि नामस्थान की तरह कुछ हो, लेकिन इसके बारे में सोचने के लिए (कुछ हद तक) वर्ग अब और अधिक समझ में आता है। –

8

आप योग्य नाम छोटे कर लिए एक typedef उपयोग करने पर विचार हो सकता है:

typedef CatState C; 

या, यदि कॉलम एक तरीका है कि वे आसानी से उत्पन्न किया जा सकता में दोहराव कर रहे हैं, तो आप प्रत्येक उत्पन्न करने के लिए मैक्रो का उपयोग पर विचार हो सकता तालिका में पंक्ति, जो बहुत संक्षिप्त (और पढ़ने में आसान) कोड का कारण बन सकती है।

+0

तो आप कह रहे हैं कि enums के लिए 'नेमस्पेस का उपयोग कर' के बराबर नहीं है? यदि ऐसा है, तो एक छोटा टाइपिफ़ मेरे लिए सबसे अच्छा समाधान जैसा लगता है। –

+0

मुझे नहीं पता कि, नहीं। आप प्रत्येक गणक के लिए एक उपयोग घोषणा का उपयोग करने में सक्षम हो सकते हैं (उदाहरण के लिए, 'CatState :: नींद;', आदि का उपयोग करके), लेकिन मैं 100% निश्चित नहीं हूं। यदि कोड अत्यधिक दोहराया गया है, हालांकि, मैं दृढ़ता से एक मैक्रो की सिफारिश करता हूं। –

+0

+1 मैंने आपके टाइपिफ़ सुझाव का उपयोग करके समाप्त किया, लेकिन निकोल ने मेरे प्रश्न का सीधा जवाब दिया। काश मैं दोनों उत्तरों को स्वीकार कर सकता हूं। –

2

निकोल का उत्तर सही है: भाषा आपको हमेशा स्कॉप्ड एन्युमरेटर्स (enum { } स्कोप को छोड़कर) को अर्हता प्राप्त करने के लिए डिज़ाइन की गई है।

हालांकि, here is a technique मैं साथ प्रगणक कि चुने हुए वर्गों के भीतर unscoped कर रहे हैं "स्कोप" के लिए आया था। तकनीकी रूप से, एन्युमेटर असुरक्षित हैं, इसलिए वे अभी भी int पर पूर्ण रूप से परिवर्तित हो जाएंगे। (नहीं "दृढ़ता से टाइप" के रूप में आप इसे डाल दिया।) फिर भी, मुहावरा में वे एक सच्चे enum नाम के बाद गुंजाइश ऑपरेटर का उपयोग करके पहुँचा रहे हैं, ताकि वाक्य रचना वहाँ एक अंतर नहीं है - और इसलिए यह सी ++ 11 की आवश्यकता है।

#define IMPORTABLE_ENUM(TYPENAME, ...) \ 
\ 
struct import_ ## TYPENAME { \ 
    enum TYPENAME { \ 
     __VA_ARGS__ \ 
    }; \ 
}; \ 
\ 
typedef import_ ## TYPENAME :: TYPENAME TYPENAME; 

// usage: 
IMPORTABLE_ENUM (duck, huey, dewey, louie) 

duck d = duck::dewey; // can't use unscoped enumerators here 

struct duck_madness : private import_duck { // but inside a derived class 
    duck who_did_it() { return huey; } // qualification is unnecessary 
}; 
2

मुझे यह संभावना भी पसंद आएगी और मुझे सीमा काफी परेशान लगती है।प्रोग्रामर यह तय करना सबसे अच्छा होता है कि वह कौन सी फीचर्स का उपयोग करना चाहता है। या तो स्पष्ट स्कोपिंग या अधिक सुविधाजनक तरीका। यदि आप प्रोग्रामर को प्रतिबंधित करते हैं तो वह या तो सुविधा के लिए पूरी सुविधा छोड़ देगा या बदसूरत वर्कअराउंड का आविष्कार करेगा, जैसे निम्न टेम्पलेट आधारित प्रकार सुरक्षित एनम। ऑप्टिमाइज़ेशन के बिना संकलित होने पर इसमें कुछ ओवरहेड होगा।

template<class _Enum> 
class type_safe_enum 
{ 
private: 
    _Enum m_EnumValue; 
    operator int(); 
public: 
    inline operator _Enum() const { return m_EnumValue; } 
    inline void operator =(_Enum x) { m_EnumValue = x; } 
}; 

enum _MY_ENUM 
{ 
    Value1, 
    Value2 
}; 

enum _MY_ENUM2 
{ 
    Value3, 
    Value4 
}; 

typedef type_safe_enum<_MY_ENUM> MY_ENUM; 

void TestMyEnum() 
{ 
    MY_ENUM myEnum; 
    int x; 

    myEnum = Value1; // ok 
    // myEnum = Value3; // compilation error 
    // myEnum = 0; // compilation error 
    // x = myEnum; // compilation error 

} 
+1

आपका '_Enum' और अन्य '_ [ए-जेड] +' पहचानकर्ता अपरिभाषित व्यवहार का कारण बनते हैं, [अंडरस्कोर के नियम] देखें [http://stackoverflow.com/a/228797/673852)। अर्थात्, 'सभी पहचानकर्ता जो अंडरस्कोर से शुरू होते हैं और या तो अपरकेस अक्षर या अन्य अंडरस्कोर हमेशा किसी भी प्रयोग के लिए आरक्षित होते हैं।'; 'यदि कार्यक्रम किसी संदर्भ में पहचानकर्ता घोषित करता है या परिभाषित करता है जिसमें यह <...> आरक्षित है, तो व्यवहार अपरिभाषित है। – Ruslan

+0

मुझे लगता है कि आप विंडोज़ दुनिया से नहीं हैं, अन्यथा आप जान लेंगे कि एमएस अपने मानक टैग टैग के साथ उस मानक का उल्लंघन करता है। मैंने यह नहीं कहा, इस कोड का उपयोग करें क्योंकि यह आपकी निजी परियोजना के लिए है। ये पहचानकर्ता आरक्षित हैं ताकि * सामान्य * प्रोग्रामर के पास नियम हो जो वे अनुसरण कर सकें और सिस्टम डेवलपर्स के साथ संघर्ष न करें। वे सिस्टम डेवलपर्स और पागल गधे डिकहेड के लिए आरक्षित हैं, जो अपनी खुद की चीजें करते हैं। मैं सिस्टम हेडर, बूटलोडर्स और ओएस कर्नेल लिखता हूं, इसलिए ये नियम मेरे लिए नहीं हैं। इस नियम का उल्लंघन करने से भी बदतर क्या मानक सी कार्यों जैसे स्ट्रैपी या एक्टटाइम का उपयोग कर रहा है। – Timo

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