दिलचस्प पोस्ट
जावा डिफ़ॉल्ट कन्स्ट्रक्टर मैं एक दिन को अजगर की तारीख से कैसे घटा सकता हूं? कैसे जावा में एक अवधि को प्रारूपित करें? (जैसे प्रारूप एच: एमएम: एसएस) जावास्क्रिप्ट / jQuery में (ई) क्या मतलब है? स्थिर स्मृति में सी ++ में एक स्ट्रिंग शब्दशः है? Matlab में आर के प्रतिनिधि के समान कार्य जैक्सब अनमरशल टाइमस्टैम्प RequireJS का उपयोग कर बैकबोन और अंडर्सको लोड करना एक ही समाधान / परियोजना में दृश्य स्टूडियो के साथ दोनों 32bit और 64bit लक्ष्यीकरण सी / सी + + मैक्रो में कॉमा PHP – फ़्लोटिंग नंबर प्रेसिजन पृष्ठ छोड़ने से पहले जावास्क्रिप्ट jQuery। भविष्य के तत्वों के लिए फ़ंक्शन के रूप में .live को बहिष्कृत किया गया है किसी भी फॉर्म डेटा को खोए बिना वर्तमान पृष्ठ को कैसे पुनः लोड करें? केंद्र और दायां संरेखित करें फ्लेक्सबॉक्स तत्व

C ++ में झंडे के रूप में एनोम का उपयोग कैसे करें?

एंगम के रूप में झंडे का इलाज करना [Flags] विशेषता के माध्यम से सी # में अच्छी तरह से काम करता है, लेकिन सी ++ में यह करने का सबसे अच्छा तरीका क्या है?

उदाहरण के लिए, मैं लिखना चाहता हूं:

 enum AnimalFlags { HasClaws = 1, CanFly =2, EatsFish = 4, Endangered = 8 }; seahawk.flags = CanFly | EatsFish | Endangered; 

हालांकि, मैं int / enum रूपांतरण के संबंध में कंपाइलर त्रुटियां प्राप्त करता है। क्या यह सिर्फ कुंद कास्टिंग से व्यक्त करने का एक अच्छा तरीका है? अधिमानतः, मैं तृतीय पक्ष पुस्तकालयों जैसे कि बढ़ावा या क्यूटी से निर्माणों पर भरोसा नहीं करना चाहता।

संपादित करें: जैसा कि उत्तर में बताया गया है, मैं seahawk.flags को int रूप में घोषित करके संकलक त्रुटि से बच सकता हूं। हालांकि, मैं टाइप सुरक्षा को लागू करने के लिए कुछ तंत्र करना चाहता हूं, इसलिए कोई seahawk.flags = HasMaximizeButton नहीं लिख सकता।

वेब के समाधान से एकत्रित समाधान "C ++ में झंडे के रूप में एनोम का उपयोग कैसे करें?"

"सही" तरीका enum के लिए बिट ऑपरेटरों को परिभाषित करना है, जैसा कि:

 enum AnimalFlags { HasClaws = 1, CanFly =2, EatsFish = 4, Endangered = 8 }; inline AnimalFlags operator|(AnimalFlags a, AnimalFlags b) {return static_cast<AnimalFlags>(static_cast<int>(a) | static_cast<int>(b));} 

आदि बिट ऑपरेटरों के बाकी यदि आवश्यक है तो enum श्रेणी int श्रेणी से अधिक है।

नोट (विषय से थोड़ी दूर): अद्वितीय झंडे बनाने का दूसरा तरीका थोड़ा बदलाव का उपयोग करके किया जा सकता है। मैं खुद को पढ़ने में आसान पाया।

 enum Flags { A = 1 << 0, // binary 0001 B = 1 << 1, // binary 0010 C = 1 << 2, // binary 0100 D = 1 << 3, // binary 1000 }; 

यह एक इंट तक मूल्य रख सकता है, जो कि ज्यादातर समय 32 झंडे हैं जो कि शिफ्ट राशि में स्पष्ट रूप से दर्शाया गया है।

मेरे जैसे आलसी लोगों के लिए, यहां प्रतिलिपि और पेस्ट करने के लिए समाधान तैयार किया गया है:

 template<class T> inline T operator~ (T a) { return (T)~(int)a; } template<class T> inline T operator| (T a, T b) { return (T)((int)a | (int)b); } template<class T> inline T operator& (T a, T b) { return (T)((int)a & (int)b); } template<class T> inline T operator^ (T a, T b) { return (T)((int)a ^ (int)b); } template<class T> inline T& operator|= (T& a, T b) { return (T&)((int&)a |= (int)b); } template<class T> inline T& operator&= (T& a, T b) { return (T&)((int&)a &= (int)b); } template<class T> inline T& operator^= (T& a, T b) { return (T&)((int&)a ^= (int)b); } 

Seahawk.flags चर किस प्रकार है?

मानक C ++ में, एन्यूमरेशन प्रकार-सुरक्षित नहीं हैं वे प्रभावी रूप से पूर्णांक हैं

पशुफ़्लैग आपके चर का प्रकार नहीं होना चाहिए, आपका चर अंतर होना चाहिए और त्रुटि समाप्त हो जाएगी।

कुछ अन्य लोगों की तरह हेक्साइडसिमल मूल्यों को लगाया जाना आवश्यक नहीं है, इसमें कोई फर्क नहीं पड़ता।

Enum मान डिफ़ॉल्ट रूप से प्रकार int रहे हैं। तो आप निश्चित रूप से बिटवर्ड कर सकते हैं या उन्हें जोड़ सकते हैं और उन्हें एक साथ रख सकते हैं और परिणाम को एक पूर्णांक में संग्रहीत कर सकते हैं।

एएनआईएम प्रकार वह इंट का एक प्रतिबंधित सबसेट है जो कि मान इसकी गणना की गई मूल्यों में से एक है। इसलिए जब आप उस सीमा के बाहर कुछ नया मूल्य बनाते हैं, तो आप इसे अपने एन्यूम प्रकार के एक चर के बिना बिना नियोजित कर सकते हैं।

यदि आप चाहें तो आप enum मान प्रकारों को भी बदल सकते हैं, लेकिन इस प्रश्न का कोई मतलब नहीं है।

संपादित करें: पोस्टर ने कहा कि वे टाइप सुरक्षा से चिंतित हैं और वे ऐसा मान नहीं चाहते हैं जो इंट प्रकार के भीतर मौजूद नहीं होना चाहिए।

लेकिन यह पशु प्रकार की प्रजातियों के चर के अंदर पशुफ़्लैग की सीमा के बाहर एक मूल्य डाल करने के लिए असुरक्षित प्रकार होगा।

हालांकि, इंट प्रकार के अंदर सीमाओं के बाहर की जांच करने का एक सुरक्षित तरीका है …

 int iFlags = HasClaws | CanFly; //InvalidAnimalFlagMaxValue-1 gives you a value of all the bits // smaller than itself set to 1 //This check makes sure that no other bits are set. assert(iFlags & ~(InvalidAnimalFlagMaxValue-1) == 0); enum AnimalFlags { HasClaws = 1, CanFly =2, EatsFish = 4, Endangered = 8, // put new enum values above here InvalidAnimalFlagMaxValue = 16 }; 

उपरोक्त आपको एक अलग एनाम से एक अमान्य फ्लैग लगाने से रोक नहीं सकता है, जिसकी कीमत 1,2,4 या 8 है।

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

सी + + 0x नोट: जोरदार टाइप किए गए एनोम

सी ++ 0x में आप अंत में टाइप सुरक्षित एनएम मान सकते हैं ….

 enum class AnimalFlags { CanFly = 2, HasClaws = 4 }; if(CanFly == 2) { }//Compiling error 

नोट करें कि आप Windows परिवेश में काम कर रहे हैं, तो एक DEFINE_ENUM_FLAG_OPERATORS मैक्रो को winnt.h में परिभाषित किया गया है जो आपके लिए काम करता है। तो इस मामले में, आप यह कर सकते हैं:

 enum AnimalFlags { HasClaws = 1, CanFly =2, EatsFish = 4, Endangered = 8 }; DEFINE_ENUM_FLAG_OPERATORS(AnimalFlags) seahawk.flags = CanFly | EatsFish | Endangered; 

ऐसा करने का सबसे आसान तरीका यहां दिखाया गया है , मानक पुस्तकालय कक्षा बिसेट का उपयोग कर।

किसी प्रकार-सुरक्षित तरीके से सी # सुविधा का अनुकरण करने के लिए, आप टेम्पलेट के लिए एक प्रकार पैरामीटर के रूप में दिए गए एक एनएएम के साथ इंट आर्गुमेंट की जगह, बिट्ससेट के चारों ओर एक टेम्पलेट आवरण लिखना होगा। कुछ इस तरह:

  template <class T, int N> class FlagSet { bitset<N> bits; FlagSet(T enumVal) { bits.set(enumVal); } // etc. }; enum MyFlags { FLAG_ONE, FLAG_TWO }; FlagSet<MyFlags, 2> myFlag; 

मुझे पता है कि ईडोलॉन द्वारा वर्तमान में स्वीकृत जवाब बहुत खतरनाक है। कंपाइलर के ऑप्टिमाइज़र इनम में संभावित मानों के बारे में अनुमान लगा सकते हैं और आप अमान्य मानों के साथ कचरा वापस ले सकते हैं। और आमतौर पर कोई भी झंडे के सभी संभव क्रमांतरों को परिभाषित नहीं करना चाहता।

जैसा कि ब्रायन आर। बॉन्डी नीचे बताता है, यदि आप सी ++ 11 का उपयोग कर रहे हैं (जो सभी को चाहिए, यह अच्छा है) अब आप enum class साथ यह अधिक आसानी से कर सकते हैं:

 enum class ObjectType : uint32_t { ANIMAL = (1 << 0), VEGETABLE = (1 << 1), MINERAL = (1 << 2) }; constexpr enum ObjectType operator |( const enum ObjectType selfValue, const enum ObjectType inValue ) { return (enum ObjectType)(uint32_t(selfValue) | uint32_t(inValue)); } // ... add more operators here. 

यह एक स्थिर आकार और मूल्य सीमा सुनिश्चित करता है constexpr लिए एक प्रकार निर्दिष्ट किया जाता है, constexpr enum class का उपयोग करके constexpr स्वचालित रूप से डाउनकास्टिंग को रोकता है, और constexpr लिए कोड को सुनिश्चित करने के लिए constexpr का उपयोग करता है और इस तरह से नियमित संख्या के रूप में ।

पूर्व -11 सी + + बोलियों के साथ रहने वाले लोगों के लिए

अगर मैं एक संकलक के साथ अटक गया था जो C + + 11 का समर्थन नहीं करता है, तो मैं उस कक्षा में एक इंट-टाइप को लपेटता हूं जो तब केवल बिटवार ऑपरेटरों का उपयोग करता है और उसके मानों को सेट करने के लिए उस एनाम से प्रकार की अनुमति देता है:

 template<class ENUM,class UNDERLYING=typename std::underlying_type<ENUM>::type> class SafeEnum { public: SafeEnum() : mFlags(0) {} SafeEnum( ENUM singleFlag ) : mFlags(singleFlag) {} SafeEnum( const SafeEnum& original ) : mFlags(original.mFlags) {} SafeEnum& operator |=( ENUM addValue ) { mFlags |= addValue; return *this; } SafeEnum operator |( ENUM addValue ) { SafeEnum result(*this); result |= addValue; return result; } SafeEnum& operator &=( ENUM maskValue ) { mFlags &= maskValue; return *this; } SafeEnum operator &( ENUM maskValue ) { SafeEnum result(*this); result &= maskValue; return result; } SafeEnum operator ~() { SafeEnum result(*this); result.mFlags = ~result.mFlags; return result; } explicit operator bool() { return mFlags != 0; } protected: UNDERLYING mFlags; }; 

आप इसे नियमित रूप से एन्यूम + टाइपपीड की तरह परिभाषित कर सकते हैं:

 enum TFlags_ { EFlagsNone = 0, EFlagOne = (1 << 0), EFlagTwo = (1 << 1), EFlagThree = (1 << 2), EFlagFour = (1 << 3) }; typedef SafeEnum<enum TFlags_> TFlags; 

और उपयोग समान है:

 TFlags myFlags; myFlags |= EFlagTwo; myFlags |= EFlagThree; if( myFlags & EFlagTwo ) std::cout << "flag 2 is set" << std::endl; if( (myFlags & EFlagFour) == EFlagsNone ) std::cout << "flag 4 is not set" << std::endl; 

और आप दूसरे टेम्प्लेट पैरामीटर का उपयोग करते हुए बाइनरी-स्थिर एंमानों (जैसे C ++ 11 enum foo : type ) के लिए अंतर्निहित प्रकार को ओवरराइड कर सकते हैं, अर्थात typedef SafeEnum<enum TFlags_,uint8_t> TFlags;

मैंने operator bool ओवरराइड को C ++ 11 के explicit कीवर्ड के explicit चिह्नित किया, जिससे इसे इंट रूपांतरण के परिणामस्वरूप रोका जा सके, क्योंकि वे झंडों का सेट 0 या 1 में लिखते समय समाप्त हो सकते हैं। यदि आप C ++ 11 का उपयोग नहीं कर सकते हैं, तो उस अधिभार को छोड़ दें और उदाहरण उपयोग में पहले सशर्त को (myFlags & EFlagTwo) == EFlagTwo

मेरी राय में अब तक के उत्तर में से कोई भी आदर्श नहीं है। आदर्श होने के लिए मैं समाधान की अपेक्षा करता हूं:

  1. == != , = , & , &= , | , पारंपरिक अर्थों में |= और ~ ऑपरेटर्स (यानी a & b )
  2. प्रकार सुरक्षित रहें यानी गैर-एन्यूमरेटेड मूल्यों जैसे कि शाब्दिक या पूर्णांक प्रकारों को निर्दिष्ट करने की अनुमति नहीं दी जाती है (इन्यूमरेटेड मानों के bitwise संयोजनों को छोड़कर) या एक पूर्णांक प्रकार को निर्दिष्ट करने के लिए एक enum चर की अनुमति दें
  3. अभिव्यक्ति पर अनुमति दें जैसे if (a & b)...
  4. बुरा मैक्रो, कार्यान्वयन विशिष्ट सुविधाओं या अन्य हैक्स की आवश्यकता नहीं है

अधिकांश समाधान अब तक 2 या 3 अंक पर गिर जाते हैं। मेरी राय में वेब डांसर बंद हो जाता है, लेकिन बिंदु 3 पर विफल रहता है और हर एनएम के लिए दोहराया जाना चाहिए।

मेरा प्रस्तावित समाधान WebDancer का एक सामान्यीकृत संस्करण है जो यह भी इंगित करता है कि बिंदु 3:

 template<typename T = typename std::enable_if<std::is_enum<T>::value, T>::type> class auto_bool { T val_; public: constexpr auto_bool(T val) : val_(val) {} constexpr operator T() const { return val_; } constexpr explicit operator bool() const { return static_cast<std::underlying_type_t<T>>(val_) != 0; } }; template <typename T = typename std::enable_if<std::is_enum<T>::value, T>::type> constexpr auto_bool<T> operator&(T lhs, T rhs) { return static_cast<T>( static_cast<typename std::underlying_type<T>::type>(lhs) & static_cast<typename std::underlying_type<T>::type>(rhs)); } template <typename T = typename std::enable_if<std::is_enum<T>::value, T>::type> constexpr T operator|(T lhs, T rhs) { return static_cast<T>( static_cast<typename std::underlying_type<T>::type>(lhs) | static_cast<typename std::underlying_type<T>::type>(rhs)); } enum class AnimalFlags : uint8_t { HasClaws = 1, CanFly = 2, EatsFish = 4, Endangered = 8 }; enum class PlantFlags : uint8_t { HasLeaves = 1, HasFlowers = 2, HasFruit = 4, HasThorns = 8 }; int main() { AnimalFlags seahawk = AnimalFlags::CanFly; // Compiles, as expected AnimalFlags lion = AnimalFlags::HasClaws; // Compiles, as expected PlantFlags rose = PlantFlags::HasFlowers; // Compiles, as expected rose = 1 // Won't compile, as expected if (seahawk != lion) {} // Compiles, as expected // if (seahawk == rose) {} // Won't compile, as expected // seahawk = PlantFlags::HasThorns; // Won't compile, as expected seahawk = seahawk | AnimalFlags::EatsFish; // Compiles, as expected lion = AnimalFlags::HasClaws | // Compiles, as expected AnimalFlags::Endangered; // int eagle = AnimalFlags::CanFly | // Won't compile, as expected // AnimalFlags::HasClaws; // int has_claws = seahawk & AnimalFlags::CanFly; // Won't compile, as expected if (seahawk & AnimalFlags::CanFly) {} // Compiles, as expected seahawk = seahawk & AnimalFlags::CanFly; // Compiles, as expected return 0; } 

यह आवश्यक ऑपरेटरों के अधिभार बनाता है लेकिन उन्हें एन्यूमरेटेड प्रकारों तक सीमित करने के लिए SFINAE का उपयोग करता है। ध्यान दें कि संक्षिप्तता के हित में मैंने सभी ऑपरेटरों को परिभाषित नहीं किया है लेकिन केवल एक ही है जो अलग है और & ; ऑपरेटर वर्तमान में वैश्विक हैं (यानी सभी एन्यूमरेटेड प्रकारों पर लागू होते हैं), लेकिन यह एक नामस्थान (जो मैं करता हूँ) में ओवरलोड कर या अतिरिक्त एसएफआईएनएई शर्तों को जोड़कर या तो संभवतः विशेष रूप से निर्मित प्रकार के उपनामों )। underlying_type_t एक सी ++ 14 सुविधा है लेकिन यह अच्छी तरह से समर्थित है और सी ++ 11 के लिए सरल template<typename T> using underlying_type_t = underlying_type<T>::type;

यदि आपका कंपाइलर अभी तक जोरदार टाइप किए गए एंमाओं का समर्थन नहीं करता है, तो आप c ++ स्रोत से निम्नलिखित आलेख को देख सकते हैं:

सार से:

इस लेख में बिट ऑपरेशन को रोकने के लिए समस्या का समाधान प्रस्तुत किया गया है
केवल सुरक्षित और वैध लोगों को अनुमति दें, और सभी अमान्य बिट जोड़तोड़ को कंपाइल-टाइम त्रुटियों में परिवर्तित करें सबसे अच्छे से, बिट ऑपरेशन का वाक्यविन्यास अपरिवर्तित रहता है, और बिट्स के साथ काम करने वाला कोड संशोधित होने की आवश्यकता नहीं है, संभवतः त्रुटियों को ठीक करने के अलावा, जो अभी तक न पहचाना गया था।

मैं खुद को एक ही सवाल पूछ रहा था और एक सामान्य सी ++ 11 आधारित समाधान के साथ आया था, जो शू के समान है:

 template <typename TENUM> class FlagSet { private: using TUNDER = typename std::underlying_type<TENUM>::type; std::bitset<std::numeric_limits<TUNDER>::max()> m_flags; public: FlagSet() = default; template <typename... ARGS> FlagSet(TENUM f, ARGS... args) : FlagSet(args...) { set(f); } FlagSet& set(TENUM f) { m_flags.set(static_cast<TUNDER>(f)); return *this; } bool test(TENUM f) { return m_flags.test(static_cast<TUNDER>(f)); } FlagSet& operator|=(TENUM f) { return set(f); } }; 

अंतरफलक स्वाद में सुधार किया जा सकता है। तो इसका उपयोग इस प्रकार किया जा सकता है:

 FlagSet<Flags> flags{Flags::FLAG_A, Flags::FLAG_C}; flags |= Flags::FLAG_D; 

सी + + मानक स्पष्ट रूप से इस बारे में बात करता है, अनुभाग देखें "17.5.2.1.3 बिटमैस्क प्रकार":

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf

आपको यह "टेम्पलेट" दिया गया है:

 enum AnimalFlags : unsigned int { HasClaws = 1, CanFly = 2, EatsFish = 4, Endangered = 8 }; constexpr AnimalFlags operator|(AnimalFlags X, AnimalFlags Y) { return static_cast<AnimalFlags>( static_cast<unsigned int>(X) | static_cast<unsigned int>(Y)); } AnimalFlags& operator|=(AnimalFlags& X, AnimalFlags Y) { X = X | Y; return X; } 

और अन्य ऑपरेटरों के लिए समान। यह भी "constexpr" ध्यान दें, यदि आप चाहते हैं कि संकलक को निष्पादित करने में सक्षम होने के लिए ऑपरेटर समय संकलन करें तो यह आवश्यक है।

यदि आप सी ++ / सीएलआई का उपयोग कर रहे हैं और रेफ क्लास के सदस्यों को सक्षम करने के लिए आवंटित करना चाहते हैं तो आपको इसके बजाय ट्रैकिंग संदर्भों का उपयोग करना होगा:

 AnimalFlags% operator|=(AnimalFlags% X, AnimalFlags Y) { X = X | Y; return X; } 

आप वस्तुओं और वस्तुओं के संग्रह को भ्रमित कर रहे हैं। विशेष रूप से, आप द्विआधारी झंडे के सेट के साथ बाइनरी फ़्लैग को भ्रमित कर रहे हैं। उचित समाधान इस तरह दिखाई देगा:

 // These are individual flags enum AnimalFlag // Flag, not Flags { HasClaws = 0, CanFly, EatsFish, Endangered }; class AnimalFlagSet { int m_Flags; public: AnimalFlagSet() : m_Flags(0) { } void Set( AnimalFlag flag ) { m_Flags |= (1 << flag); } void Clear( AnimalFlag flag ) { m_Flags &= ~ (1 << flag); } bool Get( AnimalFlag flag ) const { return (m_Flags >> flag) & 1; } }; 

ऊपर (काई) के रूप में या निम्नलिखित करें वास्तव में "एन्युमरेशन" हैं, जो आप करना चाहते हैं एक सेट है, इसलिए आपको वास्तव में stl :: set का उपयोग करना चाहिए

 enum AnimalFlags { HasClaws = 1, CanFly =2, EatsFish = 4, Endangered = 8 }; int main(void) { AnimalFlags seahawk; //seahawk= CanFly | EatsFish | Endangered; seahawk= static_cast<AnimalFlags>(CanFly | EatsFish | Endangered); } 

यहां बिटमैस्क के लिए एक विकल्प है यदि आपके पास वास्तव में अलग-अलग enum मानों का उपयोग नहीं है (उदा। आपको उन्हें बंद करने की आवश्यकता नहीं है) … और यदि आप द्विआधारी संगतता अर्थ को बनाए रखने के बारे में चिंतित नहीं हैं: आप परवाह नहीं कि आपके बिट्स कहाँ रहते हैं … जो आप शायद हैं इसके अलावा, आप को स्क्रॉप और एक्सेस कंट्रोल के साथ भी बेहतर नहीं होना चाहिए हममम, enums बिट क्षेत्रों के लिए कुछ अच्छी संपत्ति है … आश्चर्य है कि किसी ने कभी कोशिश की है कि 🙂

 struct AnimalProperties { bool HasClaws : 1; bool CanFly : 1; bool EatsFish : 1; bool Endangered : 1; }; union AnimalDescription { AnimalProperties Properties; int Flags; }; void TestUnionFlags() { AnimalDescription propertiesA; propertiesA.Properties.CanFly = true; AnimalDescription propertiesB = propertiesA; propertiesB.Properties.EatsFish = true; if( propertiesA.Flags == propertiesB.Flags ) { cout << "Life is terrible :("; } else { cout << "Life is great!"; } AnimalDescription propertiesC = propertiesA; if( propertiesA.Flags == propertiesC.Flags ) { cout << "Life is great!"; } else { cout << "Life is terrible :("; } } 

हम देख सकते हैं कि जीवन महान है, हमारे पास असतत मूल्य हैं, और हमारे पास एक अच्छा इंटीरियर है हमारे दिल की सामग्री के लिए, जो अभी भी इसके बिट्स का क्या मतलब है का संदर्भ है सब कुछ सुसंगत और अनुमान लगाया जा रहा है … मेरे लिए … जब तक मैं माइक्रोसॉफ्ट के वीसी + + कंपाइलर वाय / अपडेट 3 को Win10 x64 पर रखता हूं और मेरे कंपाइलर फ्लैग को छू नहीं सकता हूं 🙂

भले ही सब कुछ महान हो … हम झंडे के अर्थ के रूप में कुछ संदर्भ रखते हैं, क्योंकि इसकी एक वास्तविक दुनिया में एक संघ w / बिटफ़ील्ड में, जहां आपका प्रोग्राम एक असतत कार्य से अधिक के लिए जिम्मेदार हो सकता है अभी भी गलती से (काफी आसानी से) अलग-अलग यूनियनों के दो झंडे एक साथ मिलते हैं (कहते हैं, पशुप्रेरितता और ऑब्जेक्ट प्रॉपर्टीज़, चूंकि वे दोनों हैं), तुम्हारा सभी बिट्स मिश्रण करना, जो नीचे का पता लगाने के लिए एक भयानक बग है … और मुझे कैसे पता है इस पोस्ट के कई लोग बिटमैस्क के साथ बहुत बार काम नहीं करते, क्योंकि उनका निर्माण आसान है और उन्हें बनाए रखना मुश्किल है।

 class AnimalDefinition { public: static AnimalDefinition *GetAnimalDefinition( AnimalFlags flags ); //A little too obvious for my taste... NEXT! static AnimalDefinition *GetAnimalDefinition( AnimalProperties properties ); //Oh I see how to use this! BORING, NEXT! static AnimalDefinition *GetAnimalDefinition( int flags ); //hmm, wish I could see how to construct a valid "flags" int without CrossFingers+Ctrl+Shift+F("Animal*"). Maybe just hard-code 16 or something? AnimalFlags animalFlags; //Well this is *way* too hard to break unintentionally, screw this! int flags; //PERFECT! Nothing will ever go wrong here... //wait, what values are used for this particular flags field? Is this AnimalFlags or ObjectFlags? Or is it RuntimePlatformFlags? Does it matter? Where's the documentation? //Well luckily anyone in the code base and get confused and destroy the whole program! At least I don't need to static_cast anymore, phew! private: AnimalDescription m_description; //Oh I know what this is. All of the mystery and excitement of life has been stolen away :( } 

तो फिर आप "फ्लैग" तक सीधी पहुंच को रोकने के लिए अपने संघ के घोषणापत्र को निजी बनाते हैं, और गेटर्स / सेटर्स और ऑपरेटर ओवरलोड को जोड़ना पड़ता है, फिर उस सभी के लिए एक मैक्रो बनाएं, और आप मूल रूप से सही हैं, जहां आपने शुरूआत की थी एक एन्यूएम के साथ ऐसा करते हैं

दुर्भाग्य से यदि आप अपने कोड को पोर्टेबल मानना ​​चाहते हैं, तो मुझे नहीं लगता कि किसी भी तरह से A या बिट लेआउट की गारंटी है या बी) संकलन समय पर बिट लेआउट निर्धारित करें (ताकि आप इसे ट्रैक कर सकें और कम से कम सही संस्करण / प्लेटफॉर्म आदि) बिट फ़ील्ड के साथ एक स्ट्रेट में ऑफसेट

रनटाइम में आप खेतों को स्थापित कर सकते हैं / फ़ील्ड सेट कर सकते हैं और झंडे को एक्सरिंग कर सकते हैं, जो देखने में बीट्स बदलते हैं, मुझे 100% सुसंगत, प्लेटफ़ॉर्म स्वतंत्र और पूरी तरह नियतात्मक समाधान अर्थात्: एक ENUM।

टीएल; डीआर: शत्रुओं को मत सुनना सी ++ अंग्रेजी नहीं है सिर्फ इसलिए कि सी से विरासत में मिली एक संक्षिप्त कीवर्ड की शाब्दिक परिभाषा आपके उपयोग के योग्य नहीं हो सकती है इसका मतलब यह नहीं है कि आपको इसका उपयोग नहीं करना चाहिए, जब कीवर्ड की सी और सी + + परिभाषा में आपका उपयोग केस बिल्कुल शामिल है आप स्ट्रक्क्ट्स को संरचनाओं के अलावा अन्य चीजों के मॉडल के लिए और स्कूल और सामाजिक जाति के अलावा अन्य चीजों के वर्गों का भी उपयोग कर सकते हैं। आप ऐसे मूल्यों के लिए फ्लोट का उपयोग कर सकते हैं जो मैदान पर हैं। आप उन वर्णों के लिए char का उपयोग कर सकते हैं जो न तो जलाए गए हैं और न ही एक उपन्यास, नाटक या मूवी में एक व्यक्ति हैं। किसी भी प्रोग्रामर जो शब्द भाषा के अर्थ का निर्धारण करने के लिए शब्दकोश का अर्थ निर्धारित करने के लिए डिक्शनरी में जाता है … ठीक है, मैं अपनी जीभ वहां रखूंगा।

यदि आप चाहते हैं कि आपके कोड को बोली जाने वाली भाषा के बाद तैयार किया जाए, तो आप उद्देश्य-सी में लिखना सबसे अच्छा होगा, जो संयोगवश बिटफ़ील्ड के लिए बड़े पैमाने पर उपयोग करता है।

मैं Uliwitness जवाब पर विस्तृत, सी + + 98 के लिए अपना कोड फिक्सिंग और stb std::underlying_type<> टेम्पलेट की कमी और C ++ 11 के नीचे C ++ संस्करणों में explicit कीवर्ड के लिए सुरक्षित बूल मुहावरों का उपयोग करना चाहता हूं।

मैंने इसे भी संशोधित किया है ताकि इंम मूल्य बिना किसी स्पष्ट असाइनमेंट के अनुक्रमिक हो, ताकि आप हो सकें

 enum AnimalFlags_ { HasClaws, CanFly, EatsFish, Endangered }; typedef FlagsEnum<AnimalFlags_> AnimalFlags; seahawk.flags = AnimalFlags() | CanFly | EatsFish | Endangered; 

आप फिर से कच्चे झंडे मूल्य प्राप्त कर सकते हैं

 seahawk.flags.value(); 

यहाँ कोड है

 template <typename EnumType, typename Underlying = int> class FlagsEnum { typedef Underlying FlagsEnum::* RestrictedBool; public: FlagsEnum() : m_flags(Underlying()) {} FlagsEnum(EnumType singleFlag): m_flags(1 << singleFlag) {} FlagsEnum(const FlagsEnum& original): m_flags(original.m_flags) {} FlagsEnum& operator |=(const FlagsEnum& f) { m_flags |= f.m_flags; return *this; } FlagsEnum& operator &=(const FlagsEnum& f) { m_flags &= f.m_flags; return *this; } friend FlagsEnum operator |(const FlagsEnum& f1, const FlagsEnum& f2) { return FlagsEnum(f1) |= f2; } friend FlagsEnum operator &(const FlagsEnum& f1, const FlagsEnum& f2) { return FlagsEnum(f1) &= f2; } FlagsEnum operator ~() const { FlagsEnum result(*this); result.m_flags = ~result.m_flags; return result; } operator RestrictedBool() const { return m_flags ? &FlagsEnum::m_flags : 0; } Underlying value() const { return m_flags; } protected: Underlying m_flags; }; 

ओवरलोडिंग या कास्टिंग के किसी भी गुच्छा की आवश्यकता के बिना यह मेरा समाधान है:

 namespace EFoobar { enum { FB_A = 0x1, FB_B = 0x2, FB_C = 0x4, }; typedef long Flags; } void Foobar(EFoobar::Flags flags) { if (flags & EFoobar::FB_A) // do sth ; if (flags & EFoobar::FB_B) // do sth ; } void ExampleUsage() { Foobar(EFoobar::FB_A | EFoobar::FB_B); EFoobar::Flags otherflags = 0; otherflags|= EFoobar::FB_B; otherflags&= ~EFoobar::FB_B; Foobar(otherflags); } 

मुझे लगता है कि यह ठीक है, क्योंकि हम (बिना दृढ़ता से टाइप किए गए) एन्हों और इनट्स की पहचान करते हैं।

बस एक (लंबी) साइड नोट के रूप में, यदि आप

  • दृढ़ता से टाइप किए गए enums का उपयोग करना चाहते हैं और
  • अपने झंडे के साथ भारी सा से नगण्य की आवश्यकता नहीं है
  • प्रदर्शन एक मुद्दा नहीं है

मैं इस के साथ आएगा:

 #include <set> enum class EFoobarFlags { FB_A = 1, FB_B, FB_C, }; void Foobar(const std::set<EFoobarFlags>& flags) { if (flags.find(EFoobarFlags::FB_A) != flags.end()) // do sth ; if (flags.find(EFoobarFlags::FB_B) != flags.end()) // do sth ; } void ExampleUsage() { Foobar({EFoobarFlags::FB_A, EFoobarFlags::FB_B}); std::set<EFoobarFlags> otherflags{}; otherflags.insert(EFoobarFlags::FB_B); otherflags.erase(EFoobarFlags::FB_B); Foobar(otherflags); } 

सी ++ 11 प्रारंभिक सूचियों और enum class का उपयोग कर।