简体   繁体   中英

C++ how to declare bitwise operators for different types of flags?

First, my flags set is an enum like this:

typedef enum
{
    F0 = 0,
    F1 = 1,
    F2 = 2,
    F3 = 4
} Flags1;

In CI can do any bitwise operations on them, but not in C++.

So I have the macro:

#define BIT_FLAG_OPERATORS(flags)\
inline flags operator ~(flags a) { return static_cast<flags>(~static_cast<int>(a)); }\
inline flags operator &(flags a, flags b) { return static_cast<flags>(static_cast<int>(a) & static_cast<int>(b)); }\
inline flags& operator &=(flags& a, flags b) { return a = a & b; }\
inline flags operator |(flags a, flags b) { return static_cast<flags>(static_cast<int>(a) | static_cast<int>(b)); }\
inline flags& operator |=(flags& a, flags b) { return a = a | b; }\
inline flags operator ^(flags a, flags b) { return static_cast<flags>(static_cast<int>(a) ^ static_cast<int>(b)); }\
inline flags& operator ^=(flags& a, flags b) { return a = a ^ b; }

...and I use it like this:

#ifdef __cplusplus
BIT_FLAG_OPERATORS(Flags1);
#endif

Works.

Then I make another set of flags:

typedef enum
{
    F20 = 0,
    F21 = 1,
    F22 = 2,
    F23 = 4
} Flags2;

...and use the macro:

#ifdef __cplusplus
BIT_FLAG_OPERATORS(Flags2);
#endif

...and it doesn't work, I get "conflicting declaration of C function Flags2 operator... ".

Why is that and how should I change my macro to be able to apply it for different flags types?

It would be best if it was somehow possible to apply it to ALL enums , so, somehow define the operators for all enum types, not for each type separately. But how?

EDIT:

I got it: Where my header is included, there is indeed extern "C" { . My header file is included in many places, I just missed that one and was sure there is no extern "C" { . But it was. Thanks to suggestions in comments I found it. That was it.

So the answer is that what you have already works. It's debatable whether it's a good idea to convert back to an enum, but if that's what you want, then there's nothing wrong with the code you show and it was just another bug, so you might consider deleting the question.

Here's a slightly cleaner working example:

#include <type_traits>

enum Flags1 {
    F0 = 0,
    F1 = 1,
    F2 = 2,
    F3 = 4
};

enum Flags2 {
    F20 = 0,
    F21 = 1,
    F22 = 2,
    F23 = 4
};

#define BIT_BINARY_OP(Type, Op)                 \
inline Type                                     \
operator Op(Type a, Type b)                     \
{                                               \
  return Type(int(a) Op int(b));                \
}                                               \
inline Type&                                    \
operator Op##=(Type &a, Type b)                 \
{                                               \
  return a = Type(a Op b);                      \
}

#define BIT_FLAG_OPERATORS(flags)                               \
inline flags operator~(flags a) { return flags(~int(a)); }      \
BIT_BINARY_OP(flags, &)                                         \
BIT_BINARY_OP(flags, ^)                                         \
BIT_BINARY_OP(flags, |)

BIT_FLAG_OPERATORS(Flags1);
BIT_FLAG_OPERATORS(Flags2);

int
main()
{
  auto f1 = F1|F2;
  f1 |= F3;
  [[maybe_unused]] auto f2 = ~(F20|F21);
  static_assert(std::is_same_v<decltype(f1), Flags1>);
  static_assert(std::is_same_v<decltype(f2), Flags2>);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM