Проверка флажков переполнения С++

В одном из моих классов у меня есть целое число, в котором хранится набор таких флажков перечисления:

enum AttackFlags
{
    Contact = 1,                        //Move connects with target
    Projectile = 2,                         //Attack is projectile based
    Unblockable = 4,                        //Attack can not be blocked
    UncounterableLv1 = 8,                   //Attack can't be countered except by extreme counter attack skills/status effects
    UncounterableLv2 = 16,                  //Attack can not be countered
    Flinches = 32,                          //Has a chance to stun the enemy, pushing back their next turn
    Unreflectable = 64,                     //Attack penetrates reflect. Only checked for Magic attacks
    IgnoreDefenderStatusEffects = 128,      //Ignores active status effects on the defender
    IgnoreAttackerStatusEffects = 256,      //Ignores active status effects on the attacker
    IgnoreDefenderAbilities = 512,          //Ignore the defenders abilities
    IgnoreAttackerAbilities = 1024,         //Ignore the attackers abilities
    IgnoreArmorRating = 2048,               //Ignore the defensive boosts of armor
    IgnoreWeaponRating = 4096,              //Ignore the attack boost from weapons
    HighCritical = 8192,                    //The move has an increased chance to crit
    CausesStatus = 16384,                   //Can the move cause status effects?
    Elemental = 32768,                      //Is the move elemental based?
    Unimplemented = 65536,                  //has the move been implemented yet?
    ModsTimer = 131072,                     //Does it have an effect on the target or users timer?
    Heals = 262144,                         //Does the move heal?
    SecondaryEffects = 524288,              //Attack has additional effects besides basic attack
    PhysicalAttackFlag = 1048576,           //Is the Class Physically based? I.E. blocked by Protect and Shield
    MagicAttackFlag = 2097152,              //Is the move Magically Based? I.E. is it affected by things like Shell
    MultiHit = 4194304,                     //Does it enxcapsulate more then 1 hit
    SingleUse = 8388608,                    //Attack can only be used once per battle
    DoesNotCauseDamage = 16777216
};

class Attack
{
   int AtkFlags; //Stores AttackFlags |'d together

}

Я хотел бы добавить метод к моему классу Attack со следующей подписью

bool HasAttackFlags(int flags);
Флаги

были бы многочисленными AttackFlags | 'd вместе. Если бы я только хотел проверить против одного флага, я мог бы просто и AtkFlags и флаги вместе, но потому что я должен проверять несколько возможных флагов, это не сработает. Как я могу правильно проверить несколько флагов? Я бы хотел избегать передачи вектора/набора флагов для проверки, поскольку простое объединение ряда флагов проще, чем создание вектора/набора

Заранее спасибо

EDIT:

Чтобы уточнить, что я имею в виду, у меня может быть следующее

Attack atk;
atk.AtkFlags = Contact | Projectile | Heals | MagicAttackFlag;

Затем позже я хочу проверить флаги на atk следующим образом:

bool res = atk.HasAttackFlags(Contact | Projectile);

res должно быть истинным и наоборот

bool res = atk.HasAttackFlags(Contact | Unreflectable);

должно быть ложным, потому что AtkFlags не содержит как Contact adn Unreflectable.

Ответ 1

Я не уверен, что я следую вашему вопросу, потому что вы, кажется, упоминаете очевидное решение. Итак, что не так с этим в качестве решения, очевидно, добавьте все дополнительные флаги, которые вы пожелаете:

bool HasAttackFlags(int flags) {
    return (flags&(contact|projectile))!=0;
}

РЕДАКТИРОВАТЬ: О... Я думаю, что я просто понял это, вы хотите проверить наличие 2 или более флагов в качестве набора? В этом случае вы можете просто изменить метод:

bool HasAttackFlags(int flags) {
    return (flags&(contact|projectile))==(contact|projectile);
}

Ответ 2

Это мое предложение:

Обратите внимание на использование определения перечисления, чтобы включить механизм

enum AttackFlags
{
    Contact                     = 1ul <<  0,  // Move connects with target
    Projectile                  = 1ul <<  1,  // Attack is projectile based
    Unblockable                 = 1ul <<  2,  // Attack can not be blocked
    UncounterableLv1            = 1ul <<  3,  // Attack can't be countered except by extreme counter attack skills/status effects
    UncounterableLv2            = 1ul <<  4,  // Attack can not be countered
    Flinches                    = 1ul <<  5,  // Has a chance to stun the enemy, pushing back their next turn
    Unreflectable               = 1ul <<  6,  // Attack penetrates reflect. Only checked for Magic attacks
    IgnoreDefenderStatusEffects = 1ul <<  7,  // Ignores active status effects on the defender
    IgnoreAttackerStatusEffects = 1ul <<  8,  // Ignores active status effects on the attacker
    IgnoreDefenderAbilities     = 1ul <<  9,  // Ignore the defenders abilities
    IgnoreAttackerAbilities     = 1ul << 10,  // Ignore the attackers abilities
    IgnoreArmorRating           = 1ul << 11,  // Ignore the defensive boosts of armor
    IgnoreWeaponRating          = 1ul << 12,  // Ignore the attack boost from weapons
    HighCritical                = 1ul << 13,  // The move has an increased chance to crit
    CausesStatus                = 1ul << 14,  // Can the move cause status effects?
    Elemental                   = 1ul << 15,  // Is the move elemental based?
    Unimplemented               = 1ul << 16,  // has the move been implemented yet?
    ModsTimer                   = 1ul << 17,  // Does it have an effect on the target or users timer?
    Heals                       = 1ul << 18,  // Does the move heal?
    SecondaryEffects            = 1ul << 19,  // Attack has additional effects besides basic attack
    PhysicalAttackFlag          = 1ul << 20,  // Is the Class Physically based? I.E. blocked by Protect and Shield
    MagicAttackFlag             = 1ul << 21,  // Is the move Magically Based? I.E. is it affected by things like Shell
    MultiHit                    = 1ul << 22,  // Does it enxcapsulate more then 1 hit
    SingleUse                   = 1ul << 23,  // Attack can only be used once per battle
    DoesNotCauseDamage          = 1ul << 24, 

    MaskAttack      = MagicAttackFlag | PhysicalAttackFlag,
    MaskIgnore      = IgnoreWeaponRating | IgnoreArmorRating | IgnoreAttackerAbilities | IgnoreDefenderAbilities | IgnoreAttackerStatusEffects,
    // etc
};

static bool HasAttackFlag(AttackFlags flags)
{
    return flags & MaskAttack;
}

static bool HasIgnoreFlag(AttackFlags flags)
{
    return flags & MaskIgnore;
}

В качестве дополнительного бонуса рассмотрите способ возврата только "miscellanous" (un-masked, так сказать) флагов:

static AttackFlags MiscFlags(AttackFlags flags)
{
    return (AttackFlags) (flags & ~(MaskAttack | MaskIgnore));
}

Ответ 3

В качестве примера вы можете сделать это:

int v = Unblockable | UncounterableLv1| UncounterableLv;
if ((flags & v ) == v)
{
  //flags has all three: Unblockable, UncounterableLv1 and UncounterableLv
}
else if ( (flags & v ) ==  (Unblockable | UncounterableLv1))
{
  //flags has Unblockable and UncounterableLv1
}
else if ( (flags & v ) ==  Unblockable )
{
  //flags has Unblockable only
}
//and so on