EDIT: Turns out that constexpr and inline is not used if not sending the optimizer argument (-O3) to the compiler. I'm looking into verifying correct inlining and will change the code if needed for it to happen.
A templated version (put in a header file) with support for changing multiple bits (works on AVR microcontrollers btw):
namespace bit { template <typename... Args>T1, typename T2> constexpr autoinline T1 bitmask(Args...T2 argsbit) {return (T1)1 << bit;} template <typename autoT1, masktypename =T3, 0u;typename ...T2> constexpr inline forT1 bitmask(autoT3 xbit, :T2 {args...}bits) { {return mask((T1)1 |=<< 1ubit) <<| x;bitmask<T1>(bits...);} /** } Set these bits (others returnretain mask; their state) } */ template <typename T1, typename ...T2> constexpr inline void set (T1 &variable, T2 bit...bits) {variable |= (bitmask<T1>(T1bits...)1;} << bit/** Set only these bits (others will be cleared);} */ template <typename T1, typename ...T2> constexpr inline void set setOnly (T1 &variable, T2 ...bits) {variable |== bitmaskbitmask<T1>(bits...);} template <typename T1, typename T2> /** Clear inlinethese voidbits clear(T1 &variable, T2 bit)others {variableretain &=their ~((T1state)1 << bit);}*/ template <typename T1, typename ...T2> constexpr inline void clear (T1 &variable, T2 ...bits) {variable &= ~bitmask~bitmask<T1>(bits...);} template <typename T1, typename T2> /** inlineFlip voidthese flipbits (T1 &variable, T2 bit)others {variableretain ^=their ((T1state)1 << bit);}*/ template <typename T1, typename ...T2> constexpr inline void flip (T1 &variable, T2 ...bits) {variable ^= bitmaskbitmask<T1>(bits...);} /** Check if any of these bits are set */ template <typename T1, typename ...T2> constexpr inline bool isSet isAnySet(const T1 &variable, T2 bit...bits) {return variable & (bitmask<T1>(T1)1 << bitbits...);} /** Check if all these bits are set */ template <typename T1, typename ...T2> constexpr inline voidbool isSet (const T1 &variable, T2 ...bits) {return ((variable & bitmaskbitmask<T1>(bits...)) == bitmaskbitmask<T1>(bits...));} /** Check if all these bits are not set */ template <typename T1, typename ...T2> constexpr inline bool isAnySetisNotSet (const T1 &variable, T2 ...bits) {return ((variable & bitmaskbitmask<T1>(bits...)) != bitmask<T1>(bits...));} } BTW: It turns out that constexpr and inline is not used if not sending the optimizer argument (e.g.: -O3) to the compiler. Feel free to try the code at https://godbolt.org/ and look at the ASM output.