ฉันพบว่าคำตอบที่ยอมรับโดยeidolonอันตรายเกินไป เครื่องมือเพิ่มประสิทธิภาพของคอมไพเลอร์อาจตั้งสมมติฐานเกี่ยวกับค่าที่เป็นไปได้ใน enum และคุณอาจได้รับขยะกลับด้วยค่าที่ไม่ถูกต้อง และมักจะไม่มีใครต้องการที่จะกำหนดวิธีเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมดในธง enums
ดังที่ Brian R. Bondy ระบุไว้ด้านล่างหากคุณใช้ C ++ 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.
สิ่งนี้ช่วยให้แน่ใจว่ามีขนาดและช่วงค่าที่มั่นคงโดยการระบุประเภทสำหรับ enum, ยับยั้งการ downcasting อัตโนมัติของ enums ถึง ints ฯลฯ โดยการใช้enum class
และใช้constexpr
เพื่อให้แน่ใจว่าโค้ดสำหรับตัวดำเนินการได้รับการอินไลน์
สำหรับคนที่ติดอยู่กับภาษาถิ่น 11-C ++
หากฉันติดอยู่กับคอมไพเลอร์ที่ไม่รองรับ C ++ 11 ฉันจะใช้การห่อแบบ int ในคลาสที่อนุญาตให้ใช้ตัวดำเนินการระดับบิตเท่านั้นและประเภทจาก enum นั้นเพื่อตั้งค่า:
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 + typedef ปกติ:
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;
และคุณยังสามารถแทนที่ประเภทพื้นฐานสำหรับ enums ไบนารีที่มีเสถียรภาพ (เช่น C ++ 11 enum foo : type
) typedef SafeEnum<enum TFlags_,uint8_t> TFlags;
โดยใช้พารามิเตอร์แม่แบบที่สองคือ
ฉันทำเครื่องหมายการoperator bool
แทนที่ด้วยexplicit
คำหลักของ C ++ 11 เพื่อป้องกันไม่ให้เกิดการแปลง int เนื่องจากอาจทำให้ชุดค่าสถานะสิ้นสุดลงเป็น 0 หรือ 1 เมื่อเขียนออกมา ถ้าคุณไม่สามารถใช้ภาษา C ++ 11 (myFlags & EFlagTwo) == EFlagTwo
ออกเกินที่ออกและเขียนเงื่อนไขแรกในการใช้งานเช่นเป็น
[Flags]
คุณลักษณะใช้งานได้ดีเช่น:[Flags] enum class FlagBits{ Ready = 1, ReadMode = 2, WriteMode = 4, EOF = 8, Disabled = 16};