#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;
    }
}