| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
For the new experimental compiler of Rebuild language project I needed all kinds of flags. This ended up being a rabbit hole. Here is what I digged out of that.
Basically taken from C to C++.
enum Animals {
ANIMALS_CAT = 1 << 0,
ANIMALS_DOG = 1 << 1,
ANIMALS_WOLF = 1 << 3,
};
// define operator to prevent fallback to int
auto operator|(Animals a, Animals b) -> Animals { return Animals(int(a) | b); }
auto operator&(Animals a, Animals b) -> Animals { return Animals(int(a) & b); }
// define stream operator for bitmask
auto operator<<(std::ostream &out, Animals a) -> std::ostream & {
// …see main.cpp for details
}
void usage() {
auto a = ANIMALS_CAT | ANIMALS_DOG;
std::cout << a << '\n';
std::cout << ((a & ANIMALS_CAT) | ANIMALS_WOLF) << '\n';
}References:
Advantages:
Disadvantages:
The entries inside the enum class are the bit mask for each flag.
enum class Animal {
Cat = 1 << 0,
Dog = 1 << 1,
Wolf = 1 << 3,
};
using Animals = classic::Flags<Animal>;
ENABLE_CLASSIC_FLAGS_OP(Animals)
// stream operator for a single value
auto operator<<(std::ostream &out, Animal a) -> std::ostream & {
// …see main.cpp for details
}
void usage() {
auto a = Animal::Cat | Animal::Dog;
std::cout << a << '\n';
std::cout << ((a & Animal::Cat) | Animal::Wolf) << '\n';
}References:
Advantages:
Disadvantages:
Restrictions:
New modification of the classical enum class approach.
The entries contain the bit number of the flag.
enum class Animal { Cat, Dog, Wolf = 3 };
using Animals = bitnumber::Flags<Animal>;
ENABLE_BITNUMBER_FLAGS_OP(Animals)
// stream operator for a single value
auto operator<<(std::ostream &out, Animal a) -> std::ostream & {
// …see main.cpp for details
}
void usage() {
auto a = Animal::Cat | Animal::Dog;
std::cout << a << '\n';
std::cout << ((a & Animal::Cat) | Animal::Wolf) << '\n';
}References:
Advantages:
Disadvantages:
Restrictions:
All flags are represented by tag types.
Hint: A tag type is a type we only use to get a unique name.
struct Animal {
struct Cat;
struct Dog;
struct Wolf;
};
using Animals = tagtype::Flags<Animal::Cat, Animal::Dog, void, Animal::Wolf>;
auto operator<<(std::ostream &out, tagtype::Flag<Animal::Cat>) -> std::ostream & {
return out << "Cat";
} // … repeated for other types
void usage() {
auto a = Animals(Flag<Animal::Cat>, Flag<Animal::Dog>);
std::cout << a << '\n';
std::cout << (a & Flag<Animal::Cat> | Flag<Animal::Wolf>) << '\n';
}References:
Advantages:
Disadvantages:
Restrictions:
Each flag is represented by a tag value.
enum class Animal { Cat, Dog };
enum class AnimalWolf {}; // any type allowed
using Animals = tagvalue::Flags<Animal::Cat, Animal::Dog, nullptr, AnimalWolf{}>;
using tagvalue::operator<<;
auto operator<<(std::ostream &out, tagvalue::Typed<Animal> a) -> std::ostream & {
// … see main.cpp
}
auto operator<<(std::ostream &out, tagvalue::Typed<AnimalWolf>) -> std::ostream & {
return out << "Wolf";
}
void usage() {
auto a = Animals(Flag<Animal::Cat>, Flag<Animal::Dog>);
std::cout << a << '\n';
std::cout << (a & Flag<Animal::Cat> | Flag<AnimalWolf{}>) << '\n';
}References:
Advantages:
Disadvantages:
Restrictions:
The underlying values of the tags are used as bit number.
enum class Animal { Cat, Dog, Wolf = 3 };
using Animals = repeated::Flags<Animal::Cat, Animal::Dog, Animal::Wolf>
ENABLE_REPEATED_FLAGS_OP(Animals)
auto operator<<(std::ostream &out, Animal a) -> std::ostream & {
// … see main.cpp
}
void usage() {
auto a = Animal::Cat | Animal::Dog;
std::cout << a << '\n';
std::cout << ((a & Animal::Cat) | Animal::Wolf) << '\n';
}References:
Advantages:
Disadvantages:
Restrictions:
There is no perfect solution in C++. C++17 makes some new variants more viable.
Feel free to add PR for improvements or new flag implementations.
Apache License
see LICENSE file for details.
| Back | FazBrowse Home | New Git URL |