Skip to main content
Improved code
Source Link

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.

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 with support for changing multiple bits:

namespace bit { template <typename... Args> constexpr auto bitmask(Args... args) { auto mask = 0u; for(auto x : {args...}) {   mask |= 1u << x;   }  return mask;  }  template <typename T1, typename T2> inline void set (T1 &variable, T2 bit) {variable |= ((T1)1 << bit);} template <typename T1, typename ...T2> inline void set (T1 &variable, T2 ...bits) {variable |= bitmask(bits...);}    template <typename T1, typename T2>    inline void clear(T1 &variable, T2 bit) {variable &= ~((T1)1 << bit);} template <typename T1, typename ...T2> inline void clear (T1 &variable, T2 ...bits) {variable &= ~bitmask(bits...);}    template <typename T1, typename T2>    inline void flip (T1 &variable, T2 bit) {variable ^= ((T1)1 << bit);} template <typename T1, typename ...T2> inline void flip (T1 &variable, T2 ...bits) {variable ^= bitmask(bits...);} template <typename T1, typename T2>  inline bool isSet (T1 &variable, T2 bit) {return variable & ((T1)1 << bit);} template <typename T1, typename ...T2> inline void isSet (T1 &variable, T2 ...bits) {return ((variable & bitmask(bits...)) == bitmask(bits...));} template <typename T1, typename ...T2>  inline bool isAnySet(T1 &variable, T2 ...bits) {return variable & bitmask(bits...);} } 

A templated version (put in a header file) with support for changing multiple bits (works on AVR microcontrollers btw):

namespace bit { template <typename T1, typename T2> constexpr inline T1 bitmask(T2 bit)  {return (T1)1 << bit;} template <typename T1, typename T3, typename ...T2> constexpr inline T1 bitmask(T3 bit, T2 ...bits) {return ((T1)1 << bit) | bitmask<T1>(bits...);}    /** Set these bits (others retain their state) */ template <typename T1, typename ...T2> constexpr inline void set (T1 &variable, T2 ...bits)  {variable |= bitmask<T1>(bits...);}  /** Set only these bits (others will be cleared) */ template <typename T1, typename ...T2> constexpr inline void setOnly (T1 &variable, T2 ...bits)  {variable = bitmask<T1>(bits...);} /** Clear these bits (others retain their state) */ template <typename T1, typename ...T2>   constexpr inline void clear (T1 &variable, T2 ...bits)  {variable &= ~bitmask<T1>(bits...);} /** Flip these bits (others retain their state) */ template <typename T1, typename ...T2> constexpr inline void flip (T1 &variable, T2 ...bits)  {variable ^= bitmask<T1>(bits...);}   /** Check if any of these bits are set */ template <typename T1, typename ...T2>   constexpr inline bool isAnySet(const T1 &variable, T2 ...bits)  {return variable & bitmask<T1>(bits...);} /** Check if all these bits are set */ template <typename T1, typename ...T2> constexpr inline bool isSet (const T1 &variable, T2 ...bits)  {return ((variable & bitmask<T1>(bits...)) == bitmask<T1>(bits...));} /** Check if all these bits are not set */ template <typename T1, typename ...T2> constexpr inline bool isNotSet (const T1 &variable, T2 ...bits)  {return ((variable & bitmask<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.

deleted 283 characters in body
Source Link

EDIT: Turns out that constexpr and inline is useless here since it will never be a constexpr. I tried putting it onnot used if not sending the "inline functions"optimizer argument (also those not using bitmask), but no luck when looking at the compiled assembly. The in-lining will not happen either. I guess C++ still sucks when it comes to optimizing code which should be easyO3) to figure out at compile time... Hence the code below works fine; but the assembly is bloated with function callscompiler. I'm looking into verifying correct inlining and will change the code inside of themif needed for it to set or check the bitshappen.

EDIT: Turns out that constexpr is useless here since it will never be a constexpr. I tried putting it on the "inline functions" (also those not using bitmask), but no luck when looking at the compiled assembly. The in-lining will not happen either. I guess C++ still sucks when it comes to optimizing code which should be easy to figure out at compile time... Hence the code below works fine; but the assembly is bloated with function calls and the code inside of them to set or check the bits.

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.

added 498 characters in body
Source Link

EDIT: Turns out that constexpr is useless here since it will never be a constexpr. I tried putting it on the "inline functions" (also those not using bitmask), but no luck when looking at the compiled assembly. The in-lining will not happen either. I guess C++ still sucks when it comes to optimizing code which should be easy to figure out at compile time... Hence the code below works fine; but the assembly is bloated with function calls and the code inside of them to set or check the bits.

A templated version with support for changing multiple bits:

A templated version with support for changing multiple bits:

EDIT: Turns out that constexpr is useless here since it will never be a constexpr. I tried putting it on the "inline functions" (also those not using bitmask), but no luck when looking at the compiled assembly. The in-lining will not happen either. I guess C++ still sucks when it comes to optimizing code which should be easy to figure out at compile time... Hence the code below works fine; but the assembly is bloated with function calls and the code inside of them to set or check the bits.

A templated version with support for changing multiple bits:

Added a version with support for (optionally) multiple bits
Source Link
Loading
Fixed test_all()
Source Link
Loading
Source Link
Loading