R>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования. Например, так называемые opague декларации, с внешними списками:
R>
R>enum class Flags : unsigned {};
R>constexpr Flags one = 1;
R>constexpr Flags two = 2;
R>constexpr Flags one = 4;
R>
Что-то не работает именно так. А как правильно, что-то не нагуглилось
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, удусекшл, Вы писали:
У>>Полистал тут интернеты, некоторые собаководы пишут, что enum class для флагов использовать плохо
R>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.
Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?
Здравствуйте, удусекшл, Вы писали:
У>В догонку BFE>>Правильно: сделать отдельный тип для результата operator | над элементами перечисления. Но правильно никто не делает.
У>Только не operator|, а operator&, наверное
Это зависит от того, что вы делаете.
У>В принципе, как вариант. Но иногда его нужно и по назначению использовать — результат использовать не как bool, а как тот же enum. Как бы это разрулить?
Я говорю немного о другом. Есть перечисление влагов — это enum, а вот набор из нескольких флагов — это уже нечто большее, чем перечисление, это набор.
Если бы у меня было время и мне было не лень, то работу с флагами я бы описал как-то так:
enum class Flag : unsigned
{
Up = 1, Down=2, Left=4, Right=8
};
struct FlagSet
{
unsigned m_set;
explicit FlagSet(Flag flag) { m_set = flag;} // иногда набор состоит из одного флагаexplicit FlagSet(unsigned set) : m_set(set){} // возможно этот конструктор нужно сделать приватным, а некоторые операторы сделать друзьями
// добавить конструкторов при необходимостиoperator bool() // todo: bool safe idiome
{
return 0 == set; // return true
}
};
// объединение флагов дают набор
FlagSet operator | (Flag flag1, Flag flag2)
{
return (unsigned)flag1 | (unsigned)flag2;
}
// объединение наборов дают набор
FlagSet operator | (FlagSet mod1, FlagSet mod2)
{
return mod1.m_set | mod2.m_set;
}
// пересечение наборов дают набор
FlagSet operator & (FlagSet mod1, FlagSet mod2)
{
return mod1.m_set & mod2.m_set;
}
// пересечение набора и флага дают true если флаг присутствует в набореbool operator & (FlagSet mod, Flag flag)
{
return mod.m_set & (unsigned) flag;
}
// пересечение набора и флага дают true если флаг присутствует в набореbool operator & (Flag flag, FlagSet mod)
{
return mod & flag;
}
....
Здравствуйте, B0FEE664, Вы писали:
У>>В принципе, как вариант. Но иногда его нужно и по назначению использовать — результат использовать не как bool, а как тот же enum. Как бы это разрулить? BFE>Я говорю немного о другом. Есть перечисление влагов — это enum, а вот набор из нескольких флагов — это уже нечто большее, чем перечисление, это набор.
BFE>Если бы у меня было время и мне было не лень, то работу с флагами я бы описал как-то так:
Ок, в целом понятно. Только не понятно, зачем вводить новую сущность? Ну, может оно так и правильно, но как-то после целочисленных флагов несколько непривычно. И можно же обойтись просто структурой, в которой завернут анонимный старый добрый бесклассовый enum
Здравствуйте, удусекшл, Вы писали:
У>Ок, в целом понятно. Только не понятно, зачем вводить новую сущность?
Набор флагов — это реально новая сущьность и для отображения этого факта я ввожу новый тип FlagSet. FlagSet, кстати, следует сделать шаблонным, так как он не зависит от конкретного набора флагов.
У>Ну, может оно так и правильно, но как-то после целочисленных флагов несколько непривычно. И можно же обойтись просто структурой, в которой завернут анонимный старый добрый бесклассовый enum
Есть те, кто для расстояния, времени и скорости вводят отдельные типы, а есть те, кто записывает значения в переменные одного типа float. И те и другие могут писать качественные продукты. Тут вопрос в том, на что разработчикам нравится тратить время: на медленное построение строгой системы типов и быструю отладку или на быстрое написание кода и медленную отладку.
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте, удусекшл, Вы писали:
У>Полистал тут интернеты, некоторые собаководы пишут, что enum class для флагов использовать плохо
Собаководы абсолютно правы. Набор флагов — это совсем не перечисление. И запихивать невпихуемое — не самая лучшая идея.
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте
У>Сделал я enum class и сделал для него bitwise операторы, чтобы использовать в качестве флагов. Теперь я хочу такой флаг проверить по & и сделать то или иное, в зависимости от того, установлен этот флаг или нет. Но компилятор мне не дает — он не знает как получить из этого enum булево выражение.
А что мешает сделать функцию для проверки установлен флаг или нет?
вместо
if (a & b) ...
писать
if (a.has(b)) ...
ps: А bitwise операторах реализовал битовые сдвиги влево и вправо
Здравствуйте, kov_serg, Вы писали:
_>А что мешает сделать функцию для проверки установлен флаг или нет? _>вместо _>if (a & b) ... _>писать _>if (a.has(b)) ...
У enum'а?
_>ps: А bitwise операторах реализовал битовые сдвиги влево и вправо
Здравствуйте, удусекшл, Вы писали:
R>>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.
У>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?
Ну, не то чтобы совсем не предоставлен: перечисления можно использовать в switch, их можно сравнивать друг с другом. Для перечислений по-прежнему доступна zero-initialization: выражения Flags{} и Flags() конструируют "нулевой" объект перечисления, независимо от того, присутствует ли ноль в списке элементов. А значит, всегда есть возможность написать проверку: if (flags != Flags{}). Я думаю, explicit конверсию в bool просто прошляпили. И, рано или поздно, разберутся как следует и накажут кого попало, как говорится.
Здравствуйте, удусекшл, Вы писали:
У>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?
А пока что, я думаю, не будет большим грехом заюзать для преобразования в udnerlying type какой-нибудь унарный оператор: унарный плюс, разыменование...
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, удусекшл, Вы писали:
R>>>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.
У>>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?
R>Ну, не то чтобы совсем не предоставлен: перечисления можно использовать в switch, их можно сравнивать друг с другом. Для перечислений по-прежнему доступна zero-initialization: выражения Flags{} и Flags() конструируют "нулевой" объект перечисления, независимо от того, присутствует ли ноль в списке элементов. А значит, всегда есть возможность написать проверку: if (flags != Flags{}). Я думаю, explicit конверсию в bool просто прошляпили. И, рано или поздно, разберутся как следует и накажут кого попало, как говорится.
Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.
Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
B>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
Ну, а как быть, если в языке ничего нет для типизированных флагов?
Кстати, насколько помню, такого вроде нигде нет.
Разве только в шарпе. Но и там — это enum, который ты атрибутами помечаешь, как флаги. Особо ничем не отличается от обычного enum, впрочем, только значение в строковое представление начинает форматировать по-другому.
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте, boomer, Вы писали:
B>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
У>Ну, а как быть, если в языке ничего нет для типизированных флагов?
Запилить свой тип?
У>Кстати, насколько помню, такого вроде нигде нет. У>Разве только в шарпе. Но и там — это enum, который ты атрибутами помечаешь, как флаги. Особо ничем не отличается от обычного enum, впрочем, только значение в строковое представление начинает форматировать по-другому.
Здравствуйте, boomer, Вы писали:
B>Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.
А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, boomer, Вы писали:
B>>Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.
R>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?
Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional. Любая неявность — это потенциальное место для дефектов.
Здравствуйте, boomer, Вы писали:
B>>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
У>>Ну, а как быть, если в языке ничего нет для типизированных флагов?
B>Запилить свой тип?
Ну вот, все и пилят, кто во что горазд. Но хотелось бы иметь такое на уровне ядра языка, ну, или хотя бы, на уровне стандартной библиотеки.
Ну, во первых, это сложно назвать нормальным языком
А во вторых — это не языковое средство, а библиотечное, что, имхо, хуже.
И, кстати, когда оно там появилось?
Здравствуйте, boomer, Вы писали:
R>>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?
B>Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional.
Так а почему ТО можно натянуть, а ЭТО нельзя?
B>Любая неявность — это потенциальное место для дефектов.
А кто, где и что говорил про неявность? Речь же шла об операторе if. А это явное преобразование.
Здравствуйте, удусекшл, Вы писали:
У>Здравствуйте, boomer, Вы писали:
B>>>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
У>>>Ну, а как быть, если в языке ничего нет для типизированных флагов?
B>>Запилить свой тип?
У>Ну вот, все и пилят, кто во что горазд. Но хотелось бы иметь такое на уровне ядра языка, ну, или хотя бы, на уровне стандартной библиотеки.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, boomer, Вы писали:
R>>>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?
B>>Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional.
R>Так а почему ТО можно натянуть, а ЭТО нельзя?
B>>Любая неявность — это потенциальное место для дефектов.
R>А кто, где и что говорил про неявность? Речь же шла об операторе if. А это явное преобразование.
Тогда, скажи пожалуйста, что обозначает в терминах перечислений значение, для которого вообще нет перечисления? А идея создавать объект, для которого вообще нет перечисления — еще более вредная, ИМХО.
"Типизированные" перечисления (enum class : int) — это вообще какой-то нонсенс. Попытка новый механизм сделать совместимым со старым, который и хотели починить.