Joe
Joe

Reputation: 3160

How to use bitmask_operators.hpp with namespace and classes

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

Answers (1)

Joe
Joe

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

Related Questions