1 #ifndef TEST_BITMASK_TYPE_HPP 2 #define TEST_BITMASK_TYPE_HPP 3 4 #include <type_traits> 5 #include <cassert> 6 7 #include "test_macros.h" 8 9 10 template <class EnumType, EnumType Val1, EnumType Val2, 11 class UT = typename std::underlying_type<EnumType>::type, 12 UT UVal1 = static_cast<UT>(Val1), 13 UT UVal2 = static_cast<UT>(Val2), 14 UT UZero = static_cast<UT>(0), 15 EnumType Zero = static_cast<EnumType>(0) 16 > 17 struct check_bitmask_type { 18 19 static constexpr UT dcast(EnumType e) { return static_cast<UT>(e); } 20 static constexpr UT unpromote(decltype((~UZero)) promoted) { return static_cast<UT>(promoted); } 21 // We need two values that are non-zero and share at least one bit. 22 static_assert(Val1 != Zero && Val2 != Zero, ""); 23 static_assert(Val1 != Val2, ""); 24 static_assert((UVal1 & UVal2) == 0, ""); 25 26 27 static bool check() 28 { 29 { 30 EnumType ValRef = Val1; 31 ASSERT_SAME_TYPE(EnumType, decltype(Val1 & Val2)); 32 ASSERT_SAME_TYPE(EnumType, decltype(Val1 | Val2)); 33 ASSERT_SAME_TYPE(EnumType, decltype(Val1 ^ Val2)); 34 ASSERT_SAME_TYPE(EnumType, decltype((~Val1))); 35 ASSERT_SAME_TYPE(EnumType&, decltype(ValRef &= Val2)); 36 ASSERT_SAME_TYPE(EnumType&, decltype(ValRef |= Val2)); 37 ASSERT_SAME_TYPE(EnumType&, decltype(ValRef ^= Val2)); 38 } 39 40 static_assert((Val1 & Zero) == Zero, ""); 41 static_assert((Val1 & Val1) == Val1, ""); 42 static_assert(dcast(Val1 & Val2) == (UVal1 & UVal2), ""); 43 44 static_assert((Val1 | Zero) == Val1, ""); 45 static_assert(dcast(Val1 | Val2) == (UVal1 | UVal2), ""); 46 47 static_assert((Val1 ^ Zero) == Val1, ""); 48 static_assert(dcast(Val1 ^ Val2) == (UVal1 ^ UVal2), ""); 49 50 static_assert(dcast(~Zero) == unpromote(~UZero), ""); 51 static_assert(dcast(~Val1) == unpromote(~UVal1), ""); 52 53 { 54 EnumType e = Val1; 55 EnumType& eref = (e &= Val2); 56 assert(&eref == &e); 57 assert(dcast(eref) == (UVal1 & UVal2)); 58 } 59 { 60 EnumType e = Val1; 61 EnumType& eref = (e |= Val2); 62 assert(&eref == &e); 63 assert(dcast(eref) == (UVal1 | UVal2)); 64 } 65 { 66 EnumType e = Val1; 67 EnumType& eref = (e ^= Val2); 68 assert(&eref == &e); 69 assert(dcast(eref) == (UVal1 ^ UVal2)); 70 } 71 return true; 72 } 73 }; 74 75 #endif // TEST_BITMASK_TYPE 76