Как сделать функции с флаговыми параметрами? (C++)

Я почти всегда заканчиваю тем, что использовал MIT или BSD (они эквивалентны), начиная с него

  1. самая либеральная лицензия там. Это просто говорит, что Вы не ответственны ни за какой вид проблемы, и дополнительно вынуждает людей включать уведомление об авторском праве Вашей исходной работы в производных.
  2. Это позволяет производные с закрытым исходным кодом, который является чем-то, что я рассматриваю как хорошую вещь: компании иногда не имеют возможности сделать их работу под GPL (они могут самостоятельно использовать продукты или компоненты от третьего лица с ограниченными лицензиями).

, Что, и набор GNU/GPL обычно экстремисты, когда Вы встречаетесь с ними в дикой природе.

10
задан 19 October 2009 в 15:07
поделиться

6 ответов

Вы можете определить перечисление, определяющее «однобитовые» значения (обратите внимание, что включающая структура действует здесь только как контекст именования, так что вы можете написать, например, MyFlags :: EVEN ):

struct MyFlags{
    enum Value{
        EVEN                           = 0x01,
        ODD                            = 0x02,
        ANOTHER_FLAG                   = 0x04,
        YET_ANOTHER_FLAG               = 0x08,
        SOMETHING_ELSE                 = 0x10,
        SOMETHING_COMPLETELY_DIFFERENT = 0x20
    };
};

, а затем используйте его так:

int CreateNum(MyFlags::Value flags){
    if (flags & MyFlags::EVEN){
        // do something...
    }
}

void main(){
    CreateNum((MyFlags::Value)(MyFlags::EVEN | MyFlags::ODD));
}

или просто так:

int CreateNum(int flags){
    if (flags & MyFlags::EVEN){
        // do something...
    }
}

void main(){
    CreateNum(MyFlags::EVEN | MyFlags::ODD);
}

Вы также можете просто объявить целочисленные константы, но, на мой взгляд, перечисление более четкое.

Примечание: Я обновил сообщение, чтобы учесть некоторые комментарии, спасибо!

29
ответ дан 3 December 2019 в 13:32
поделиться

Я поддержал ответ orsogufo, но мне всегда нравилось делать следующее для определения значений:

enum Value{
  EVEN                           = (1<<0),
  ODD                            = (1<<2),        
  ANOTHER_FLAG                   = (1<<3),        
  YET_ANOTHER_FLAG               = (1<<4),        
  SOMETHING_ELSE                 = (1<<5),        
  SOMETHING_COMPLETELY_DIFFERENT = (1<<6),

  ANOTHER_EVEN                   = EVEN|ANOTHER_FLAG
};

<< - оператор сдвига. Увеличение правой части позволяет вам генерировать последовательные битовые маски, перемещая 1 по одному биту за раз. Это те же значения для простых флагов, но для меня легче читается и становится очевидным, если вы пропустите или дублируете значение.

Мне также нравится комбинировать некоторые общие комбинации флагов, когда это необходимо.

11
ответ дан 3 December 2019 в 13:32
поделиться

Вы ошиблись в тестах. Вам нужно что-то вроде (flags & EVEN) , где EVEN - это целое число с одним набором битов (1, 2, 4, 8, 16 - некоторая степень двойки). (Целое число может быть int или enum. У вас может быть макрос, но это, как правило, не очень хорошая идея.)

Вы можете использовать указанную вами нотацию, перегрузив flags :: operator == (flagvalue е) , но это плохая идея.

0
ответ дан 3 December 2019 в 13:32
поделиться
enum flags {
    EVEN =        0x0100,
    ODD =         0x0200,
    BELOW_TEN =   0x0400,
    ABOVETEN =    0x0800,
    HUNDRED =     0x1000,
    MASK =        0xff00
};

void some_func(int id_and_flags)
{
    int the_id = id_and_flags & ~MASK;
    int flags = id_and_flags & MASK;
    if ((flags & EVEN) && (the_id % 2) == 1)
        ++the_id;
    if ((flags & ODD) && (the_id % 2) == 0)
        ++the_id;
    // etc
}

Также иллюстрирует маскирование битовых полей, которое может быть полезно, когда вам просто нужно добавить упрощенную дополнительную функциональность без добавления какой-либо дополнительной структуры данных.

0
ответ дан 3 December 2019 в 13:32
поделиться

Вы можете использовать const int следующим образом:

const int FLAG1 = 0x0001;
const int FLAG2 = 0x0010;
const int FLAG3 = 0x0100;
// ...

И когда вы его используете:

int CreateNum(int flags)
{
    if( flags & FLAG1 )
        // FLAG1 is present

    if( flags & FLAG2 )
        // FLAG2 is present

    // ...
}

Конечно, вы можете установить один или несколько флагов в свои флаги, используя | оператор.

5
ответ дан 3 December 2019 в 13:32
поделиться

Используйте степень двойки как отдельные константы , например

enum Flags { EVEN = 0x1, ODD = 0x2, GREATER_TEN = 0x4 };

, и вы используете логический оператор и "&" для тестирования, например

if( flags & GREATER_THAN_TEN)
    num = 11;
if( (flags & EVEN) && (num % 2) == 1 )
    num++;
else if ( (flags & ODD) && (num % 2) == 0 )
    num++;
return num;
1
ответ дан 3 December 2019 в 13:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: