#include <iostream>
#include <bitset>
std::bitset<4> flag_out(int f) {
return std::bitset<4>(f);
}
#include <climits>
// For CHAR_BIT.
#include <cstdint>
// For uint8_t.
// Underlying flag type. Change as needed. Should remain unsigned.
typedef uint8_t flag_t;
// Helper functions, to provide cleaner syntax to the enum.
// Not actually necessary, they'll be evaluated at compile time either way.
constexpr flag_t flag(int f) {
return 1 << f;
}
constexpr flag_t fl_validate(int f) {
return (f ? (1 << f) + fl_validate(f - 1) : 1);
}
constexpr flag_t register_invalids(int f) {
return static_cast<flag_t>(-1) - fl_validate(f - 1);
}
// List of available flags.
enum BitFlag : flag_t {
FFalse = flag(0), // 0001
FTrue = flag(1), // 0010
FDefault = flag(2), // 0100
FToggle = flag(3), // 1000
// ...
// Number of defined flags.
FLAG_COUNT = 4,
// Indicator for invalid flags.
FLAG_INVALID = register_invalids(FLAG_COUNT),
// Maximum number of available flags.
FLAG_MAX = sizeof(flag_t) * CHAR_BIT
};
void func(flag_t f) {
if (f & FLAG_INVALID) throw "Invalid flags, yo!";
if (f & FFalse) std::cout << "Flag: FFalse." << std::endl;
if (f & FTrue) std::cout << "Flag: FTrue." << std::endl;
if (f & FDefault) std::cout << "Flag: FDefault." << std::endl;
if (f & FToggle) std::cout << "Flag: FToggle." << std::endl;
std::cout << std::endl;
}
int main() {
std::cout << "False: " << flag_out(FFalse) << '\n'
<< "True: " << flag_out(FTrue) << '\n'
<< "Default: " << flag_out(FDefault) << '\n'
<< "Toggle: " << flag_out(FToggle) << '\n'
<< "False + True: " << flag_out(FFalse | FTrue) << '\n'
<< "False + Default: " << flag_out(FFalse | FDefault) << '\n'
<< "False + Toggle: " << flag_out(FFalse | FToggle) << '\n'
<< "True + Default: " << flag_out(FTrue | FDefault) << '\n'
<< "True + Toggle: " << flag_out(FTrue | FToggle) << '\n'
<< "Default + Toggle: " << flag_out(FDefault | FToggle) << '\n'
<< "False + True + Default: " << flag_out(FFalse | FTrue | FDefault) << '\n'
<< "False + True + Toggle: " << flag_out(FFalse | FTrue | FToggle) << '\n'
<< "True + Default + Toggle: " << flag_out(FTrue | FDefault | FToggle) << '\n'
<< "All four: " << flag_out(FFalse | FTrue | FDefault | FToggle) << std::endl << std::endl;
func(FFalse);
func(FFalse | FTrue);
func(FFalse | FDefault);
func(FFalse | FToggle);
func(FFalse | FTrue | FDefault);
func(FFalse | FTrue | FToggle);
func(FFalse | FDefault | FToggle);
func(FFalse | FTrue | FDefault | FToggle);
func(FTrue);
func(FTrue | FDefault);
func(FTrue | FToggle);
func(FTrue | FDefault | FToggle);
func(FDefault);
func(FDefault | FToggle);
func(FToggle);
std::cout << "Invalid flags: " << std::bitset<8>(FLAG_INVALID) << std::endl;
try {
func(16);
} catch (const char* p) {
std::cout << p << std::endl;
}
}