Reputation: 3160
I want to use C++11 enum class
as bitfields and find a nice approach here.
But I stuck, if my enum class declaration is not in global namespace but in custom namespace or inside of a class instead. E.g.:
#define ENABLE_BIT_OPERATORS(E) template<> struct enable_bitmask_operators<E> { static constexpr bool enable=true; };
// anonymous namespace
namespace {
enum class Ean {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ean)
} // anonymous namespace
// custom namespace
namespace Custom {
enum class Ecn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ecn)
} // custom namespace
// inside class in global namespace
class MyclassGN {
public:
enum class Ecgn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ecgn)
};
// inside class in anonymous namespace
namespace {
class MyclassAN {
public:
enum class Ecan {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ecan)
};
} // anonymous namespace
// inside class in custom namespace
namespace Custom {
class MyclassGN {
public:
enum class Ecgn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ecgn)
};
} // custom namespace
This always gives me errors:
error: specialization of 'template<class E> struct enable_bitmask_operators' in different namespace
until I place my template specialization to the same namespace as the template enable_bitmask_operators
in bitmask_operators.hpp
is located (global namespace in this case).
But I want to have my specialization close to my enum class declaration.
In the mentioned article, this problem is also commented by Jay Miller and it seems that he provides a solution. But I failed to follow his hints to solve this in bitmask_operators.hpp
.
Example code here.
Edit / partially solved: I meanwhile, I got it work (just a dump copy & paste issue and cryptic error messages ;-). I'd just updated my example code by applying Jay Millers constexpr function solution.
But there is still an issue when declaring the enum class inside of a class. The issue raises, when I add a ctor to my class, like:
class MyclassGN {
public:
enum class Ecgn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
ENABLE_BIT_OPERATORS(Ecgn)
explicit MyclassGN(Ecgn e_) {}
};
Then I got an error:
enclosing class of constexpr non-static member function 'bool MyclassGN::enable_bitmask_operators(MyclassGN::Ecgn)' is not a literal type
Well, I fixed this by adding static
keyword:
class MyclassGN {
public:
enum class Ecgn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
static ENABLE_BIT_OPERATORS(Ecgn)
explicit MyclassGN(Ecgn e_) {}
};
But the next issue raises when I try to use the bitmask operators, e.g.:
class MyclassGN {
public:
enum class Ecgn {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
static ENABLE_BIT_OPERATORS(Ecgn)
explicit MyclassGN(Ecgn e_): e(e_) {
e |= Ecgn::Bit3;
}
private:
Ecgn e;
};
I got an error:
no match for 'operator|=' (operand types are 'MyclassGN::Ecgn' and 'MyclassGN::Ecgn')
Updated example which shows the error is located here.
Upvotes: 0
Views: 760
Reputation: 3160
Example code, based on Anthony Williams' bitmask_operators.hpp
and also applied Jay Millers suggestion (constexpr function instead of template<> struct) to fix the namespace issue is located here.
Note that when declaring the enum class inside of a class, the constexpr function needs to be preceded by the friend
keyword (as dyp suggested in the comment below). Example:
class Myclass {
public:
enum class E {
None = 0x00,
Bit0 = 0x01,
Bit1 = 0x02,
Bit2 = 0x04,
Bit3 = 0x08,
};
friend ENABLE_BIT_OPERATORS(E)
};
Upvotes: 2