Re[3]: enum class and if expression
От: удусекшл  
Дата: 18.12.19 15:03
Оценка:
Здравствуйте, rg45, Вы писали:


R>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования. Например, так называемые opague декларации, с внешними списками:


R>
R>enum class Flags : unsigned {};

R>constexpr Flags one = 1;
R>constexpr Flags two = 2;
R>constexpr Flags one = 4;

R>


Что-то не работает именно так. А как правильно, что-то не нагуглилось
Re[3]: enum class and if expression
От: удусекшл  
Дата: 18.12.19 15:10
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, удусекшл, Вы писали:


У>>Полистал тут интернеты, некоторые собаководы пишут, что enum class для флагов использовать плохо


R>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.


Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?
Re[3]: enum class and if expression
От: B0FEE664  
Дата: 18.12.19 15:28
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>В догонку

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

....
И каждый день — без права на ошибку...
Re[4]: enum class and if expression
От: удусекшл  
Дата: 18.12.19 15:37
Оценка:
Здравствуйте, B0FEE664, Вы писали:

У>>В принципе, как вариант. Но иногда его нужно и по назначению использовать — результат использовать не как bool, а как тот же enum. Как бы это разрулить?

BFE>Я говорю немного о другом. Есть перечисление влагов — это enum, а вот набор из нескольких флагов — это уже нечто большее, чем перечисление, это набор.

BFE>Если бы у меня было время и мне было не лень, то работу с флагами я бы описал как-то так:


Ок, в целом понятно. Только не понятно, зачем вводить новую сущность? Ну, может оно так и правильно, но как-то после целочисленных флагов несколько непривычно. И можно же обойтись просто структурой, в которой завернут анонимный старый добрый бесклассовый enum
Re[5]: enum class and if expression
От: B0FEE664  
Дата: 18.12.19 16:19
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Ок, в целом понятно. Только не понятно, зачем вводить новую сущность?

Набор флагов — это реально новая сущьность и для отображения этого факта я ввожу новый тип FlagSet. FlagSet, кстати, следует сделать шаблонным, так как он не зависит от конкретного набора флагов.

У>Ну, может оно так и правильно, но как-то после целочисленных флагов несколько непривычно. И можно же обойтись просто структурой, в которой завернут анонимный старый добрый бесклассовый enum


Есть те, кто для расстояния, времени и скорости вводят отдельные типы, а есть те, кто записывает значения в переменные одного типа float. И те и другие могут писать качественные продукты. Тут вопрос в том, на что разработчикам нравится тратить время: на медленное построение строгой системы типов и быструю отладку или на быстрое написание кода и медленную отладку.
И каждый день — без права на ошибку...
Re[4]: enum class and if expression
От: rg45 СССР  
Дата: 18.12.19 16:32
Оценка:
Здравствуйте, удусекшл, Вы писали:

R>>
R>>enum class Flags : unsigned {};

R>>constexpr Flags one = 1;
R>>constexpr Flags two = 2;
R>>constexpr Flags one = 4;

R>>


У>Что-то не работает именно так. А как правильно, что-то не нагуглилось


Пардон, наспех писал. Вот так правильно:

enum class Flags : unsigned;

constexpr auto one = Flags(1);
constexpr auto two = Flags(2);
constexpr auto four = Flags(4);


Можно вместо auto явно писать Flags, это уже кому как нравится.
--
Re[2]: enum class and if expression
От: boomer  
Дата: 18.12.19 17:47
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте, удусекшл, Вы писали:


У>Полистал тут интернеты, некоторые собаководы пишут, что enum class для флагов использовать плохо


Собаководы абсолютно правы. Набор флагов — это совсем не перечисление. И запихивать невпихуемое — не самая лучшая идея.
Re: enum class and if expression
От: kov_serg Россия  
Дата: 18.12.19 18:15
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте


У>Сделал я enum class и сделал для него bitwise операторы, чтобы использовать в качестве флагов. Теперь я хочу такой флаг проверить по & и сделать то или иное, в зависимости от того, установлен этот флаг или нет. Но компилятор мне не дает — он не знает как получить из этого enum булево выражение.

А что мешает сделать функцию для проверки установлен флаг или нет?
вместо
if (a & b) ...
писать
if (a.has(b)) ...

ps: А bitwise операторах реализовал битовые сдвиги влево и вправо
Re[2]: enum class and if expression
От: удусекшл  
Дата: 19.12.19 08:41
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>А что мешает сделать функцию для проверки установлен флаг или нет?

_>вместо
_>if (a & b) ...
_>писать
_>if (a.has(b)) ...

У enum'а?


_>ps: А bitwise операторах реализовал битовые сдвиги влево и вправо


Не распарсил
Re[4]: enum class and if expression
От: rg45 СССР  
Дата: 19.12.19 10:17
Оценка:
Здравствуйте, удусекшл, Вы писали:

R>>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.


У>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?


Ну, не то чтобы совсем не предоставлен: перечисления можно использовать в switch, их можно сравнивать друг с другом. Для перечислений по-прежнему доступна zero-initialization: выражения Flags{} и Flags() конструируют "нулевой" объект перечисления, независимо от того, присутствует ли ноль в списке элементов. А значит, всегда есть возможность написать проверку: if (flags != Flags{}). Я думаю, explicit конверсию в bool просто прошляпили. И, рано или поздно, разберутся как следует и накажут кого попало, как говорится.
--
Отредактировано 19.12.2019 10:22 rg45 . Предыдущая версия . Еще …
Отредактировано 19.12.2019 10:21 rg45 . Предыдущая версия .
Re[4]: enum class and if expression
От: rg45 СССР  
Дата: 19.12.19 10:51
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?


А пока что, я думаю, не будет большим грехом заюзать для преобразования в udnerlying type какой-нибудь унарный оператор: унарный плюс, разыменование...

http://coliru.stacked-crooked.com/a/1eb70e86550f0a05

#include <iostream>
#include <type_traits>
#include <utility>

template <typename T>
std::enable_if_t<std::is_enum_v<T>, std::underlying_type_t<T>> operator + (T e) {
    return std::underlying_type_t<T>(e);
}

template <typename T>
std::enable_if_t<std::is_enum_v<T>, std::underlying_type_t<T>> operator * (T e) {
    return +e;
}

enum class Flags : unsigned {
    one = 1,
    two = 2,
    four = 4,
};

int main() {
    if (+Flags::one)
        std::cout << "Ok" << std::endl;

    if (*Flags::two)
        std::cout << "Ok" << std::endl;
}
--
Отредактировано 19.12.2019 12:05 rg45 . Предыдущая версия . Еще …
Отредактировано 19.12.2019 10:57 rg45 . Предыдущая версия .
Отредактировано 19.12.2019 10:57 rg45 . Предыдущая версия .
Отредактировано 19.12.2019 10:56 rg45 . Предыдущая версия .
Отредактировано 19.12.2019 10:55 rg45 . Предыдущая версия .
Отредактировано 19.12.2019 10:53 rg45 . Предыдущая версия .
Re[5]: enum class and if expression
От: boomer  
Дата: 19.12.19 14:32
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, удусекшл, Вы писали:


R>>>Есть такое мнение. Но я бы не стал это воспринимать как истину в последней инстанции. Особенно с учетом всех требований стандарта. Многое указывает на то, что именно под такое использование подгонялись современные требования.


У>>Хм, возможно. Но тогда почему не предоставлен механизм для использования в условных конструкциях?


R>Ну, не то чтобы совсем не предоставлен: перечисления можно использовать в switch, их можно сравнивать друг с другом. Для перечислений по-прежнему доступна zero-initialization: выражения Flags{} и Flags() конструируют "нулевой" объект перечисления, независимо от того, присутствует ли ноль в списке элементов. А значит, всегда есть возможность написать проверку: if (flags != Flags{}). Я думаю, explicit конверсию в bool просто прошляпили. И, рано или поздно, разберутся как следует и накажут кого попало, как говорится.


Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.

Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.
Re[6]: enum class and if expression
От: удусекшл  
Дата: 19.12.19 14:35
Оценка:
Здравствуйте, boomer, Вы писали:


B>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.


Ну, а как быть, если в языке ничего нет для типизированных флагов?

Кстати, насколько помню, такого вроде нигде нет.
Разве только в шарпе. Но и там — это enum, который ты атрибутами помечаешь, как флаги. Особо ничем не отличается от обычного enum, впрочем, только значение в строковое представление начинает форматировать по-другому.
Re[7]: enum class and if expression
От: boomer  
Дата: 19.12.19 14:39
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте, boomer, Вы писали:



B>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.


У>Ну, а как быть, если в языке ничего нет для типизированных флагов?


Запилить свой тип?

У>Кстати, насколько помню, такого вроде нигде нет.

У>Разве только в шарпе. Но и там — это enum, который ты атрибутами помечаешь, как флаги. Особо ничем не отличается от обычного enum, впрочем, только значение в строковое представление начинает форматировать по-другому.

Вообще-то в нормальных языках давно есть.
https://docs.oracle.com/javase/7/docs/api/java/util/EnumSet.html
Re[6]: enum class and if expression
От: rg45 СССР  
Дата: 19.12.19 14:40
Оценка:
Здравствуйте, boomer, Вы писали:

B>Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.


А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?
--
Re[7]: enum class and if expression
От: boomer  
Дата: 19.12.19 14:48
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, boomer, Вы писали:


B>>Преобразование в bool для перечисления не имеет смысл. Если, конечно, не использовать его как набор флагов. Но это само по себе, как забивание гвоздей микроскопом.


R>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?


Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional. Любая неявность — это потенциальное место для дефектов.
Re[8]: enum class and if expression
От: удусекшл  
Дата: 19.12.19 14:51
Оценка:
Здравствуйте, boomer, Вы писали:

B>>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.


У>>Ну, а как быть, если в языке ничего нет для типизированных флагов?


B>Запилить свой тип?


Ну вот, все и пилят, кто во что горазд. Но хотелось бы иметь такое на уровне ядра языка, ну, или хотя бы, на уровне стандартной библиотеки.


B>Вообще-то в нормальных языках давно есть.

B>https://docs.oracle.com/javase/7/docs/api/java/util/EnumSet.html

Ну, во первых, это сложно назвать нормальным языком
А во вторых — это не языковое средство, а библиотечное, что, имхо, хуже.
И, кстати, когда оно там появилось?
Re[8]: enum class and if expression
От: rg45 СССР  
Дата: 19.12.19 14:53
Оценка:
Здравствуйте, boomer, Вы писали:

R>>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?


B>Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional.


Так а почему ТО можно натянуть, а ЭТО нельзя?

B>Любая неявность — это потенциальное место для дефектов.


А кто, где и что говорил про неявность? Речь же шла об операторе if. А это явное преобразование.
--
Отредактировано 19.12.2019 15:05 rg45 . Предыдущая версия . Еще …
Отредактировано 19.12.2019 15:00 rg45 . Предыдущая версия .
Re[9]: enum class and if expression
От: boomer  
Дата: 19.12.19 15:05
Оценка:
Здравствуйте, удусекшл, Вы писали:

У>Здравствуйте, boomer, Вы писали:


B>>>>Я вообще заметил, что плюсовики любят использовать инструменты языка совсем не так, как они задумывались. Согласен, правда, что в некоторых случаях такое использование достаточно удобно.


У>>>Ну, а как быть, если в языке ничего нет для типизированных флагов?


B>>Запилить свой тип?


У>Ну вот, все и пилят, кто во что горазд. Но хотелось бы иметь такое на уровне ядра языка, ну, или хотя бы, на уровне стандартной библиотеки.



B>>Вообще-то в нормальных языках давно есть.

B>>https://docs.oracle.com/javase/7/docs/api/java/util/EnumSet.html

У>Ну, во первых, это сложно назвать нормальным языком


На вкус и цвет все фломастеры разные.

У>А во вторых — это не языковое средство, а библиотечное, что, имхо, хуже.


Если это находится в стандартной библиотеке — то никакой разницы.

У>И, кстати, когда оно там появилось?


September 2004
Re[9]: enum class and if expression
От: boomer  
Дата: 19.12.19 15:08
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, boomer, Вы писали:


R>>>А для обычных чисел — целых, с плавающей точкой — это преобразование имеет смысл?


B>>Это еще можно натянуть. Например, как специальное значение. И даже в этом случае лучше использовать optional.


R>Так а почему ТО можно натянуть, а ЭТО нельзя?


B>>Любая неявность — это потенциальное место для дефектов.


R>А кто, где и что говорил про неявность? Речь же шла об операторе if. А это явное преобразование.


Тогда, скажи пожалуйста, что обозначает в терминах перечислений значение, для которого вообще нет перечисления? А идея создавать объект, для которого вообще нет перечисления — еще более вредная, ИМХО.

"Типизированные" перечисления (enum class : int) — это вообще какой-то нонсенс. Попытка новый механизм сделать совместимым со старым, который и хотели починить.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.