не нравится. Что это делает? Меняет тип. Значит Александреску хочет нажухать систему типов малозаметным плюсом. Идея так себе.
enum class PersonId {};
enum class ManagerId {};
std::optional<Manager> find(ManagerId id) {...}
...
const auto id = PersonId{42}; // допустим прочитали из базыconst auto manager = find(ManagerId{+id}); // ну ошибка, мягко говоря, в глаза не бросаетсяconst auto manager = find(ManagerId{std::to_underlying(id)}); // здесь мне кажется легче увидеть, что кто-то явно спятил
ну и val получился типа int а должен был быть MyEnum. К тому же это переопределение может быть некорректно
enum class Meters {}
enum class Kilometers {}
auto operator+(Meters m, Kilometers k) { return Meters { m + k * 1000}; }
enum class был введён для усиления системы типов. А введения скрытого преобразования типа — это шаг назад. Если не нужна строгость, можно использовать обычный enum.
Здравствуйте, Sm0ke, Вы писали:
S>Александреску предложил перегрузить унарный префиксный оператор + для всех енумов для получения их underlying value
Я тоже делаю перегрузку унарного плюса, но перегружаю только для is_scoped_enum (который С++23, но легко реализуем через is_enum<T> + !convertible_to<T,underlying_type<T>>).
Для non-scoped enum унарный плюс и так работает за счёт интегрального продвижения.
Разница в типе: встроенный унарный плюс даёт int, тогда как самописный может давать честный underlying type.
С одной стороны, хотелось бы иметь одинаковое поведение для scoped и non-scoped enums (а именно underlying_type), с другой — не хочется повлиять на существующий код (например, foo(+non_coped_enum_val) вызовет разные перегрузки в зависимости от того, видно ли в точке вызова определение operator+(T) -> underlying_type<T>).
Я понимаю, что вероятность нарваться на связанные с этим проблемы невелика, но и больших преимуществ от приведения non-scoped enum именно к underlying, а не int тоже нет, а там, где есть, лучше явно позвать to_underlying. Так что я выбираю безопасность (в плане невлияния на существующий код).
Здравствуйте, koenjihyakkei, Вы писали: K>Идея нравится, только звездочка, мне кажется, органичнее бы смотрелась:
На мой взгляд, в С++ префиксная звёздочка семантически крепко ассоциируется с получением значения, на которое есть некий указатель или другой косвенный "хранитель" (типа optional). использование его для целей получения underlying type мне видится сомнительной идеей.
Опять же, скажем, если есть
enum EN{ A, B, C };
optional<EN> o;
то код
auto x = +o.value();
auto x = +*o;
смотрится лучше/понятнее (на мой вкус), чем
auto x = *o.value();
auto x = **o;
Кроме того, префисный плюс можно применять в шаблонном коде (не обязательно значит, что нужно), так что он будет равно успешно работать как со встроенными интегральными типами, так и с перечислениями.
Здравствуйте, koenjihyakkei, Вы писали:
K>Ну, например, сразу доступны все арифметические операции для енамов:
А зачем?
В тех редких случаях когда такое надо над enums проводить лучше добавить конкретную операцию для конкретного enum, а не лепить один костыль для всех.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, serg_joker, Вы писали:
_>Здравствуйте, koenjihyakkei, Вы писали: K>>Идея нравится, только звездочка, мне кажется, органичнее бы смотрелась:
_>На мой взгляд, в С++ префиксная звёздочка семантически крепко ассоциируется с получением значения, на которое есть некий указатель или другой косвенный "хранитель" (типа optional). использование его для целей получения underlying type мне видится сомнительной идеей.
_>Опять же, скажем, если есть _>
_>enum EN{ A, B, C };
_>optional<EN> o;
_>
_>то код
_>
_>auto x = +o.value();
_>auto x = +*o;
_>
_>смотрится лучше/понятнее (на мой вкус), чем
_>
_>auto x = *o.value();
_>auto x = **o;
_>
_>Кроме того, префисный плюс можно применять в шаблонном коде (не обязательно значит, что нужно), так что он будет равно успешно работать как со встроенными интегральными типами, так и с перечислениями.
Здравствуйте, koenjihyakkei, Вы писали:
SP>>не нравится. Что это делает? K>Ну, например, сразу доступны все арифметические операции для енамов:
Вот как раз такого следует избегать. Если над enum class совершаются арифметические операции, значит мы имеем дело с неверно выбранным типом. enum class имеет смысл преобразовывать в значение только если значение этого перечисления надо передать через какой-то интерфейс не умеющий работать с произвольными типами. Более того, если в enum class задаётся числовое значение для какого либо элемента, то этот код уже подозрителен.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, koenjihyakkei, Вы писали:
SP>>>не нравится. Что это делает? K>>Ну, например, сразу доступны все арифметические операции для енамов:
BFE>Вот как раз такого следует избегать. Если над enum class совершаются арифметические операции, значит мы имеем дело с неверно выбранным типом. enum class имеет смысл преобразовывать в значение только если значение этого перечисления надо передать через какой-то интерфейс не умеющий работать с произвольными типами. Более того, если в enum class задаётся числовое значение для какого либо элемента, то этот код уже подозрителен.
Вроде да, а вроде и нет. Как быть с битовыми масками? Ввели бы в язык флаговый тип, то я бы с вами скорее всего согласился.
Здравствуйте, Sm0ke, Вы писали:
S>Вроде да, а вроде и нет. Как быть с битовыми масками? Ввели бы в язык флаговый тип, то я бы с вами скорее всего согласился.
Для битовых масок я бы писал отдельный класс с константами. Но если хочется enum, то зачем именно enum class? Можно просто enum:
Здравствуйте, Sm0ke, Вы писали:
S>Вроде да, а вроде и нет. Как быть с битовыми масками?
Добавь constexpr ... operator | (...) для своего типа с битовыми масками
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока