operator* для enum class
От: B0FEE664  
Дата: 21.09.21 09:15
Оценка: 7 (2) :))
Надоело писать static_cast'ы и функции для конвертации enum ---> int.

А что если перегрузить оператор * :

enum class TestE
{
   a,
   b
};

unsigned int operator* (TestE x)
{
   return TestE::a == x ? 0 : 1;
};


   TestE asdf = TestE::b;

   unsigned int v = *asdf;
   unsigned int vv = *TestE::b;


Слишком неожиданно?
Кто-нибудь так делал?
Есть подводные камни?

тест
И каждый день — без права на ошибку...
Re: operator* для enum class
От: watchmaker  
Дата: 21.09.21 09:29
Оценка: 13 (4) +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Надоело писать static_cast'ы и функции для конвертации enum ---> int.


BFE>Слишком неожиданно?

BFE>Кто-нибудь так делал?

Достаточно неожиданно встретить перегрузку operator*, когда все для этих целей перегружают унарный operator+
Унарный плюс ведь уже делает integral promotion у других типов — удивления меньше.

В том числе для старых unscoped перечислений, которые были до enum class, встроенный плюс используется и работает именно таким образом:
enum Enum {
    Foo
};

void fn(Enum);
void fn(int);

void test() {
    fn(Foo);   // вызов перегрузки  void fn(Enum)
    fn(+Foo);  // вызов перегрузки  void fn(int)
}


BFE>unsigned int operator* (TestE x)

BFE>{
BFE> return TestE::a == x ? 0 : 1;
BFE>};
В эту сторону проще сделать (возможно в шаблоне для всех enum)

return static_cast<std::underlying_type_t<TestE>>(x);

и навсегда забыть об ручном выписывании значений.
Отредактировано 23.09.2021 10:35 watchmaker . Предыдущая версия . Еще …
Отредактировано 22.09.2021 20:14 watchmaker . Предыдущая версия .
Re[2]: operator* для enum class
От: B0FEE664  
Дата: 21.09.21 09:43
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Достаточно неожиданно встретить перегрузку operator*, когда все для этих целей перегружают унарный operator+

W>Унарный плюс ведь уже делает integral promotion у других типов — удивления меньше.

Что-ж. Плюс, так плюс. Так и запишем.
И каждый день — без права на ошибку...
Re[2]: operator* для enum class
От: · Великобритания  
Дата: 23.09.21 12:06
Оценка: +3
Здравствуйте, watchmaker, Вы писали:

w> Достаточно неожиданно встретить перегрузку operator*, когда все для этих целей перегружают унарный operator+


Объясните прожженому явщику зачем оператор? Чем явное имя функции хуже?
 void test() {
     fn(Foo);   // вызов перегрузки  void fn(Enum)
     fn(toInt(Foo));  // вызов перегрузки  void fn(int)
 }

имхо читается понятнее, чем непонятные иероглифы.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: operator* для enum class
От: B0FEE664  
Дата: 23.09.21 13:40
Оценка:
Здравствуйте, ·, Вы писали:

w>> Достаточно неожиданно встретить перегрузку operator*, когда все для этих целей перегружают унарный operator+


·>Объясните прожженому явщику зачем оператор? Чем явное имя функции хуже?

Явное имя, в котором указан тип, подразумевает, что существуют какие-то ещё функции, типа toUInt32, toUShort....

·>
·> void test() {
·>     fn(Foo);   // вызов перегрузки  void fn(Enum)
·>     fn(toInt(Foo));  // вызов перегрузки  void fn(int)
·> }
·>

·>имхо читается понятнее, чем непонятные иероглифы.

Для меня toInt(..) означает, что у вас в enum'е лежат отрицательные значения. Это уже подозрительно. Такой код означает, что надо проверять, что там fn(..) делает и какие значения у enum.

А ещё такая функция говорит, что вероятно где-то есть toEnumXXX(int) в которой, вероятно, есть UB (хотя это зависит от версии используемого стандарта).
И каждый день — без права на ошибку...
Re[4]: operator* для enum class
От: · Великобритания  
Дата: 23.09.21 13:56
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE> Явное имя, в котором указан тип, подразумевает, что существуют какие-то ещё функции, типа toUInt32, toUShort....

ок, пусть toUInt() или вообще asOrdinal() или asNumber().

Но всё равно сово-глобусный аргумент. Ведь наличие operator+ явно подразумевает наличие и -*/^ и т.п.

BFE> Для меня toInt(..) означает, что у вас в enum'е лежат отрицательные значения.

Ну в коде был int я так и написал. Какой тип использовать — это другой вопрос. Я пытаюсь понять мотивацию выбора неявного значка вместо явного слова.

BFE> Это уже подозрительно. Такой код означает, что надо проверять, что там fn(..) делает и какие значения у enum.

operator+ чем поможет?

Суть в том, что видя первый раз в жизни +Foo я не понимаю что тут хотят сказать и даже неясно как догадаться — надо лезть в доку. asOrdinal(Foo) — сразу ясно — взять порядковое значение енума.

BFE> А ещё такая функция говорит, что вероятно где-то есть toEnumXXX(int) в которой, вероятно, есть UB (хотя это зависит от версии используемого стандарта).

Да, действительно. Захочется превратить int обратно в enum и непонятно какой оператор и куда влепить.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: operator* для enum class
От: B0FEE664  
Дата: 23.09.21 14:24
Оценка:
Здравствуйте, ·, Вы писали:

BFE>> Явное имя, в котором указан тип, подразумевает, что существуют какие-то ещё функции, типа toUInt32, toUShort....

·>ок, пусть toUInt() или вообще asOrdinal() или asNumber().
·>Но всё равно сово-глобусный аргумент.
Вот и получается, что для каждого enum какая-то своя функция, не такая, как у другого enum, а хочется унификации.

·>Ведь наличие operator+ явно подразумевает наличие и -*/^ и т.п.

Это да. Мне ближе в этом плане operator*, как у смарт указателей, но... смотри ответ watchmaker.

BFE>> Для меня toInt(..) означает, что у вас в enum'е лежат отрицательные значения.

·>Ну в коде был int я так и написал. Какой тип использовать — это другой вопрос. Я пытаюсь понять мотивацию выбора неявного значка вместо явного слова.
Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.

BFE>> Это уже подозрительно. Такой код означает, что надо проверять, что там fn(..) делает и какие значения у enum.

·>operator+ чем поможет?
А он не указывает тип возвращаемого значения.

·>Суть в том, что видя первый раз в жизни +Foo я не понимаю что тут хотят сказать и даже неясно как догадаться — надо лезть в доку. asOrdinal(Foo) — сразу ясно — взять порядковое значение енума.

И не факт, что чтение доки поможет. Мне, например, не помогло.

BFE>> А ещё такая функция говорит, что вероятно где-то есть toEnumXXX(int) в которой, вероятно, есть UB (хотя это зависит от версии используемого стандарта).

·>Да, действительно. Захочется превратить int обратно в enum и непонятно какой оператор и куда влепить.
С названием функции та же ситуация.
И каждый день — без права на ошибку...
Отредактировано 23.09.2021 15:13 B0FEE664 . Предыдущая версия .
Re[4]: operator* для enum class
От: rg45 СССР  
Дата: 23.09.21 14:47
Оценка: +3
Здравствуйте, B0FEE664, Вы писали:

BFE>·>Объясните прожженому явщику зачем оператор? Чем явное имя функции хуже?

BFE>Явное имя, в котором указан тип, подразумевает, что существуют какие-то ещё функции, типа toUInt32, toUShort....

Чем плох to_underlying? Да он появляется только в C++23, но сделать собственную версию — как два пальца об асфальт. Зато сразу понятна семантика, без стеклянных шаров. И никаких намеков на то, что обязано существовать обратное преобразование не видно, по-моему.
--
Отредактировано 23.09.2021 14:54 rg45 . Предыдущая версия .
Re[6]: operator* для enum class
От: · Великобритания  
Дата: 23.09.21 20:33
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE> ·>ок, пусть toUInt() или вообще asOrdinal() или asNumber().

BFE> ·>Но всё равно сово-глобусный аргумент.
BFE> Вот и получается, что для каждого enum какая-то своя функция, не такая, как у другого enum, а хочется унификации.
Не, я имею в виду, вместо того, чтобы писать "+" лучше определять "asOrdinal" (или по вкусу) для всех enum.

Разница лишь в имени. Вместо "*" будет "asOrdinal", остальное всё так же.

BFE> BFE>> Для меня toInt(..) означает, что у вас в enum'е лежат отрицательные значения.

BFE> ·>Ну в коде был int я так и написал. Какой тип использовать — это другой вопрос. Я пытаюсь понять мотивацию выбора неявного значка вместо явного слова.
BFE> Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.
Лямбды имеют новую семантику — захват контекста и значительно всё упрощают, т.к. не надо определять тип отдельно. А тут — неясно, т.к. разница чисто синтаксическая.

BFE> BFE>> Это уже подозрительно. Такой код означает, что надо проверять, что там fn(..) делает и какие значения у enum.

BFE> ·>operator+ чем поможет?
BFE> А он не указывает тип возвращаемого значения.
Не понял. А asOrdinal чем хуже?

BFE> ·>Суть в том, что видя первый раз в жизни +Foo я не понимаю что тут хотят сказать и даже неясно как догадаться — надо лезть в доку. asOrdinal(Foo) — сразу ясно — взять порядковое значение енума.

BFE> И не факт, что чтение доки поможет. Мне, например, не помогло.
Что не помогло? Не понял.

BFE> ·>Да, действительно. Захочется превратить int обратно в enum и непонятно какой оператор и куда влепить.

BFE> С названием функции та же ситуация.
В смысле? Ты сам же написал asEnum. Единственное она должна быть шаблонной или просто overload по разным типам enum.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: operator* для enum class
От: rg45 СССР  
Дата: 23.09.21 21:29
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.


А вот не совсем все. Когда ты определяешь лямбду внутри функции с формальным параметром auto, ты фактически определяешь локальный класс с шаблонным оператором operator(). На обычных классах это сделать невозможно, потому что определение шаблонов внутри функции (любых) запрещено.
--
Отредактировано 23.09.2021 21:37 rg45 . Предыдущая версия . Еще …
Отредактировано 23.09.2021 21:31 rg45 . Предыдущая версия .
Re[7]: operator* для enum class
От: night beast СССР  
Дата: 24.09.21 06:02
Оценка:
Здравствуйте, rg45, Вы писали:

BFE>>Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.


R>А вот не совсем все. Когда ты определяешь лямбду внутри функции с формальным параметром auto, ты фактически определяешь локальный класс с шаблонным оператором operator(). На обычных классах это сделать невозможно, потому что определение шаблонов внутри функции (любых) запрещено.


не аргумент. никто не мешает вынести класс вне функции.
Re[8]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 06:26
Оценка:
Здравствуйте, night beast, Вы писали:

BFE>Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.


R>>А вот не совсем все...


NB>не аргумент. никто не мешает вынести класс вне функции.


Можно, конечно. Вопрос только в том, будет ли это "то же самое". Как минимум, изменилась область видимости класса. У класса появилось связывание. Имя классу теперь должен дать программист, а не компилятор.
--
Отредактировано 24.09.2021 6:33 rg45 . Предыдущая версия . Еще …
Отредактировано 24.09.2021 6:30 rg45 . Предыдущая версия .
Отредактировано 24.09.2021 6:30 rg45 . Предыдущая версия .
Отредактировано 24.09.2021 6:27 rg45 . Предыдущая версия .
Re[9]: operator* для enum class
От: night beast СССР  
Дата: 24.09.21 06:42
Оценка: +2
Здравствуйте, rg45, Вы писали:

R>Можно, конечно. Вопрос только в том, будет ли это "то же самое". Как минимум, изменилась область видимости класса. У класса появилось связывание. Имя классу теперь должен дать программист, а не компилятор.


имхо это все проходит по категории "синтаксический сахар"
Re[5]: operator* для enum class
От: sergii.p  
Дата: 24.09.21 07:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>Чем плох to_underlying? Да он появляется только в C++23, но сделать собственную версию — как два пальца об асфальт. Зато сразу понятна семантика, без стеклянных шаров. И никаких намеков на то, что обязано существовать обратное преобразование не видно, по-моему.


вот мне кажется, что в стандарте хотели как лучше, а получилось как всегда. std::to_underlying — слишком длинное название для такой часто встречающейся функции. Я использую имя cast. С именем области у меня вопросы. Но можно придумать тоже что-нибудь короткое трёхбуквенное (utl например).
enum class UserId{};
UserId id;
std::cout << "User id: " << utl::cast(id);


Хорошо бы ещё переопределять операторы << >>. Тогда потребность в таких функциях-костылях отпадает вовсе. Фактически надо то зачастую вычитать из базы, записать в базу, вывести в лог. Внутри всегда использовать тип без приведения. Но это конечно только в теории. На практике функцию cast я леплю постоянно.
Re[6]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 07:50
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>вот мне кажется, что в стандарте хотели как лучше, а получилось как всегда. std::to_underlying — слишком длинное название для такой часто встречающейся функции. Я использую имя cast. С именем области у меня вопросы. Но можно придумать тоже что-нибудь короткое трёхбуквенное (utl например).

SP>
SP>enum class UserId{};
SP>UserId id;
SP>std::cout << "User id: " << utl::cast(id);
SP>


По моему опыту, удачные имена — вовсе не обязательно наиболее короткие. По имени cast трудно понять тип результата. Придется напрягаться и угадывать при чтении. Имхо, лучше написать более длинное имя и исключить любые недопонимания.
--
Отредактировано 24.09.2021 7:52 rg45 . Предыдущая версия .
Re[5]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 07:57
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Чем плох to_underlying? Да он появляется только в C++23...

слишком длинное имя, но можно и его использовать, конечно.
И каждый день — без права на ошибку...
Re[6]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 07:59
Оценка: +3
Здравствуйте, B0FEE664, Вы писали:

R>>Чем плох to_underlying? Да он появляется только в C++23...

BFE>слишком длинное имя, но можно и его использовать, конечно.

Я же не предлагаю тебе использовать именно это имя. Это просто как образец подхода.

Хотя, как по мне, соотношение информативность/длина вполне адекватное. По-моему это лучше, чем когда унарный плюс используется для преобразования типов.
--
Отредактировано 24.09.2021 8:07 rg45 . Предыдущая версия . Еще …
Отредактировано 24.09.2021 8:00 rg45 . Предыдущая версия .
Re[6]: operator* для enum class
От: · Великобритания  
Дата: 24.09.21 09:23
Оценка:
Здравствуйте, B0FEE664, Вы писали:

R>>Чем плох to_underlying? Да он появляется только в C++23...

BFE>слишком длинное имя, но можно и его использовать, конечно.
Ты всё ешё в нотепаде код что-ли пишешь? В эпоху современных IDE это давно не проблема.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 09:42
Оценка:
Здравствуйте, ·, Вы писали:

·>Не, я имею в виду, вместо того, чтобы писать "+" лучше определять "asOrdinal" (или по вкусу) для всех enum.

·>Разница лишь в имени. Вместо "*" будет "asOrdinal", остальное всё так же.
Чем лучше?

BFE>> Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.

·>Лямбды имеют новую семантику — захват контекста и значительно всё упрощают, т.к. не надо определять тип отдельно.
Захват контекста можно сделать с помощью отдельного типа.

·>А тут — неясно, т.к. разница чисто синтаксическая.

Вот поэтому я и задал исходный вопрос.

BFE>> BFE>> Это уже подозрительно. Такой код означает, что надо проверять, что там fn(..) делает и какие значения у enum.

BFE>> ·>operator+ чем поможет?
BFE>> А он не указывает тип возвращаемого значения.
·>Не понял. А asOrdinal чем хуже?
Ordinal? Надо проверить, нет ли специального класса с таким именем. Если выбирать имя, то to_underlying, как подсказал rg45.

BFE>> ·>Суть в том, что видя первый раз в жизни +Foo я не понимаю что тут хотят сказать и даже неясно как догадаться — надо лезть в доку. asOrdinal(Foo) — сразу ясно — взять порядковое значение енума.

BFE>> И не факт, что чтение доки поможет. Мне, например, не помогло.
·>Что не помогло? Не понял.
Это старая тема. Есть ещё случай, где используется унарный плюс:
  Скрытый текст
проверка
#include <iostream>
#include <chrono>

class A
{
public:
  static const unsigned TIMEOUT = 300;
};


void foo(std::chrono::milliseconds timeout)
{
}


void boo()
{
  foo( std::chrono::milliseconds(A::TIMEOUT) );
  //foo( std::chrono::milliseconds(+A::TIMEOUT) ); //OK
}


int main()
{
    std::cout << "the end\n";
    return 0;
}


BFE>> ·>Да, действительно. Захочется превратить int обратно в enum и непонятно какой оператор и куда влепить.

BFE>> С названием функции та же ситуация.
·>В смысле? Ты сам же написал asEnum. Единственное она должна быть шаблонной или просто overload по разным типам enum.
Это выглядит не очень красиво:
auto en = AsEnum<SomeEnumeName>(x);
И каждый день — без права на ошибку...
Re[6]: operator* для enum class
От: RonWilson Россия  
Дата: 24.09.21 09:54
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>слишком длинное имя, но можно и его использовать, конечно.


и такое встречается и живут люди, ничего:

#define Convert_EnumValue_To_Integer(x) ((int)x)
Re[7]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 10:20
Оценка:
Здравствуйте, ·, Вы писали:

R>>>Чем плох to_underlying? Да он появляется только в C++23...

BFE>>слишком длинное имя, но можно и его использовать, конечно.
·>Ты всё ешё в нотепаде код что-ли пишешь? В эпоху современных IDE это давно не проблема.

Иногда я могу писать некомпилирующийся кусок кода в течении недели, современные IDE не очень то с таким кодом работают. И вообще, с кроссплатформенными проектами IDE не очень-то дружат: то инклюды не из той папки, то не той версии...
И каждый день — без права на ошибку...
Re[7]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 10:53
Оценка:
Здравствуйте, RonWilson, Вы писали:

RW>и такое встречается и живут люди, ничего:


RW>
RW>#define Convert_EnumValue_To_Integer(x) ((int)x)
RW>


Ну, тут перебор уже в другую сторону. Во-первых, потому, что в имени функции описываются входные параметры. Непонятно, зачем это нужно, когда входные параметры должны быть прекрасно видны как в объявлении функции (формальные параметры), так и в месте ее использования (фактические параметры). Во-вторых, лично меня всегда несколько напрягают функции начинающиеся с глаголов. Глагол как бы указывает на то, что функция имеет какие-то побочные эффекты: что-то сконвертировать, что-то добавить, что-то удалить, что-то изменить. Лично я таких функций стараюсь избегать, по возможности. А для функции без побочных эффектов, которая просто вычисляет какой-то результат, который зависит только от входных параметров, в качестве имен лучше всего подходят существительные. Подобно чистым математическим функциям: синус, косинус, логарифм... Мы же не называем эти функции calculate_log или convert_to_sin. Вот и для этой функции "To_Integer" было бы в самый раз. Еще лучше было бы просто "Integer", но тогда могут возникать коллизии между именами типов и функций. Поэтому добавляют префикс "to".
--
Отредактировано 24.09.2021 11:08 rg45 . Предыдущая версия . Еще …
Отредактировано 24.09.2021 11:04 rg45 . Предыдущая версия .
Отредактировано 24.09.2021 10:54 rg45 . Предыдущая версия .
Re[8]: operator* для enum class
От: RonWilson Россия  
Дата: 24.09.21 11:07
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Ну, тут перебор уже в другую сторону. Во-первых...


поискипано

баян не мой вот тут тоже нечто похожее, вопрос в соглашениях об именовании. У кого-то — позиция обмазать макросней так, чтобы intellisense любой IDE подвис, у кого-то — что-то свое. Тема холиварна чуть более, чем полностью, это даже хлеще, чем обсуждать пробелы и табы
Re[7]: operator* для enum class
От: sergii.p  
Дата: 24.09.21 11:13
Оценка:
Здравствуйте, rg45, Вы писали:

R>По имени cast трудно понять тип результата. Придется напрягаться и угадывать при чтении. Имхо, лучше написать более длинное имя и исключить любые недопонимания.


а по имени to_underlying можно без напряга вычислить тип результата? Точно также в IDE наводишь на функцию и видишь тип. В чистом notepad — да, это мудрено.
Re[8]: operator* для enum class
От: · Великобритания  
Дата: 24.09.21 11:14
Оценка: :)
Здравствуйте, B0FEE664, Вы писали:

BFE>>>слишком длинное имя, но можно и его использовать, конечно.

BFE>·>Ты всё ешё в нотепаде код что-ли пишешь? В эпоху современных IDE это давно не проблема.
BFE>Иногда я могу писать некомпилирующийся кусок кода в течении недели, современные IDE не очень то с таким кодом работают. И вообще, с кроссплатформенными проектами IDE не очень-то дружат: то инклюды не из той папки, то не той версии...
Не делай так.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: operator* для enum class
От: · Великобритания  
Дата: 24.09.21 11:24
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>·>Не, я имею в виду, вместо того, чтобы писать "+" лучше определять "asOrdinal" (или по вкусу) для всех enum.

BFE>·>Разница лишь в имени. Вместо "*" будет "asOrdinal", остальное всё так же.
BFE>Чем лучше?
Тем, что вместо непонятного значка будет осмысленное человекочитаемое имя.

BFE>>> Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.

BFE>·>Лямбды имеют новую семантику — захват контекста и значительно всё упрощают, т.к. не надо определять тип отдельно.
BFE>Захват контекста можно сделать с помощью отдельного типа.
Это будет отдельный тип, т.е. другая семантика, а не только синтаксис.

BFE>·>А тут — неясно, т.к. разница чисто синтаксическая.

BFE>Вот поэтому я и задал исходный вопрос.
Если бы не пытался использовать операторы, то и вопроса бы не было.

BFE>>> А он не указывает тип возвращаемого значения.

BFE>·>Не понял. А asOrdinal чем хуже?
BFE>Ordinal? Надо проверить, нет ли специального класса с таким именем. Если выбирать имя, то to_underlying, как подсказал rg45.
Выбор конкретного имени не так важен. Выбирай по вкусу. Суть в том, что это дескриптивное словесное имя, а не значок.

BFE>>> ·>Суть в том, что видя первый раз в жизни +Foo я не понимаю что тут хотят сказать и даже неясно как догадаться — надо лезть в доку. asOrdinal(Foo) — сразу ясно — взять порядковое значение енума.

BFE>>> И не факт, что чтение доки поможет. Мне, например, не помогло.
BFE>·>Что не помогло? Не понял.
BFE>Это старая тема. Есть ещё случай, где используется унарный плюс:
"unsigned TIMEOUT = 300"? Классический анекдот же:

— Петька, приборы!
— 300.
— Что 300?
— А что приборы?

Не надо так писать. Пиши сразу "milliseconds TIMEOUT = 300"

BFE>>> С названием функции та же ситуация.

BFE>·>В смысле? Ты сам же написал asEnum. Единственное она должна быть шаблонной или просто overload по разным типам enum.
BFE>Это выглядит не очень красиво:
BFE>
BFE>auto en = AsEnum<SomeEnumeName>(x);
BFE>

А какой вариант красивее?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 12:13
Оценка:
Здравствуйте, RonWilson, Вы писали:

BFE>>слишком длинное имя, но можно и его использовать, конечно.

RW>и такое встречается и живут люди, ничего:
RW>
RW>#define Convert_EnumValue_To_Integer(x) ((int)x)
RW>


В последних 4-х компаниях, что я работал такое запрещено правилами кодирования:
— C-каст запрещён;
— макросы под запретом.

И вообще: зачем так мучиться?

ЗЫ: к тому же в макросе ошибка — x не в скобках:
float foo()
{
  return 1.1f;
}

auto x = Convert_EnumValue_To_Integer(a + foo());

=> x — число с плавающей точкой.
И каждый день — без права на ошибку...
Re[9]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 12:46
Оценка:
Здравствуйте, ·, Вы писали:

BFE>>·>Не, я имею в виду, вместо того, чтобы писать "+" лучше определять "asOrdinal" (или по вкусу) для всех enum.

BFE>>·>Разница лишь в имени. Вместо "*" будет "asOrdinal", остальное всё так же.
BFE>>Чем лучше?
·>Тем, что вместо непонятного значка будет осмысленное человекочитаемое имя.
'+' и '*' вполне человекочитаемые знаки.
Они ничем не хуже '/' для std::filesystem::path
и
'->' для смарт указателей.

BFE>>>> Синтаксический сахар. Это как с лямбдами — и до них можно было всё тоже самое, но введение нового синтаксиса сильно упростило применение функций из <algorithm>.

BFE>>·>Лямбды имеют новую семантику — захват контекста и значительно всё упрощают, т.к. не надо определять тип отдельно.
BFE>>Захват контекста можно сделать с помощью отдельного типа.
·>Это будет отдельный тип, т.е. другая семантика, а не только синтаксис.
Каждая лямбда — это отдельный тип.

BFE>>·>А тут — неясно, т.к. разница чисто синтаксическая.

BFE>>Вот поэтому я и задал исходный вопрос.
·>Если бы не пытался использовать операторы, то и вопроса бы не было.
Вообще-то был бы.

·>Выбор конкретного имени не так важен. Выбирай по вкусу. Суть в том, что это дескриптивное словесное имя, а не значок.

Не согласен. Выбор имени — очень важный элемент программирования.

·>"unsigned TIMEOUT = 300"? Классический анекдот же:

·>Не надо так писать. Пиши сразу "milliseconds TIMEOUT = 300"

Вообще-то это работа с кодом написанным давно, до С++11.

BFE>>Это выглядит не очень красиво:

BFE>>
BFE>>auto en = AsEnum<SomeEnumeName>(x);
BFE>>

·>А какой вариант красивее?
Не знаю. Пока ничего красивого в голову не приходит. Если какое-то значение надо преобразовать в значение из enum, то в каждом случае это отдельная функция с проверкой входного значения, постусловиями зависящими от значений enum и, возможно, с бросанием исключения... Так что унифицированная функция вряд ли нужна. Возможно должна получится конструкция вроде:
auto enum_x = toEnum<1_x -> SomeEnumeName::one, 2_x -> SomeEnumeName::two, default_x -> []{ return SomeEnumeName::undefined; }>(x);

но в рамках C++14, с которым я сейчас работаю, это красиво не написать, наверное.
И каждый день — без права на ошибку...
Re[8]: operator* для enum class
От: RonWilson Россия  
Дата: 24.09.21 12:47
Оценка:
Здравствуйте, B0FEE664, Вы писали:

написал же — баян не мой
Re[9]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 13:43
Оценка: +1
Здравствуйте, RonWilson, Вы писали:

RW>баян не мой вот тут тоже нечто похожее, вопрос в соглашениях об именовании. У кого-то — позиция обмазать макросней так, чтобы intellisense любой IDE подвис, у кого-то — что-то свое. Тема холиварна чуть более, чем полностью, это даже хлеще, чем обсуждать пробелы и табы


Не-не, я ж понимаю и не претендую. Позволил себе лишь выразить свое отношение к вопросу, не более.
--
Re[8]: operator* для enum class
От: rg45 СССР  
Дата: 24.09.21 13:46
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>а по имени to_underlying можно без напряга вычислить тип результата? Точно также в IDE наводишь на функцию и видишь тип. В чистом notepad — да, это мудрено.


Имя to_underlying говорит, что функция преобразует аргумент к underlying типу, который, естественно, зависит от типа аргумента. И это имя в точности описывает семантику функции. Бобльше о ней ничего знать и не нужно. Имея на руках фактический параметр, я всегдя ясно понимаю, каков будет тип результата. Чего нельзя сказать про твой cast.
--
Отредактировано 24.09.2021 13:50 rg45 . Предыдущая версия . Еще …
Отредактировано 24.09.2021 13:47 rg45 . Предыдущая версия .
Re[10]: operator* для enum class
От: · Великобритания  
Дата: 24.09.21 15:40
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>Чем лучше?

BFE>·>Тем, что вместо непонятного значка будет осмысленное человекочитаемое имя.
BFE>'+' и '*' вполне человекочитаемые знаки.
BFE>Они ничем не хуже '/' для std::filesystem::path
BFE>и
BFE>'->' для смарт указателей.
'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*. Насчёт / тоже сомнительно, но это хоть более менее известное соглашение в операционках.

BFE>>>Захват контекста можно сделать с помощью отдельного типа.

BFE>·>Это будет отдельный тип, т.е. другая семантика, а не только синтаксис.
BFE>Каждая лямбда — это отдельный тип.
Семантически другой тип. Разница есть. Например, тип — анонимный и с другой областью видимости.

BFE>>>Вот поэтому я и задал исходный вопрос.

BFE>·>Если бы не пытался использовать операторы, то и вопроса бы не было.
BFE>Вообще-то был бы.
Какой? Как лучше назвать функцию?

BFE>·>Выбор конкретного имени не так важен. Выбирай по вкусу. Суть в том, что это дескриптивное словесное имя, а не значок.

BFE>Не согласен. Выбор имени — очень важный элемент программирования.
Это не так важно. Ибо если имя было выбрано неудачно, можно легко переименовать. Притом нередко IDE это сделает на раз, автоматически. С оператором сложнее.

BFE>·>"unsigned TIMEOUT = 300"? Классический анекдот же:

BFE>·>Не надо так писать. Пиши сразу "milliseconds TIMEOUT = 300"
BFE>Вообще-то это работа с кодом написанным давно, до С++11.
Я честно говоря, не очень понял смысл + в той конструкции... Почему нельзя какой-нибудь явный cast использовать для работы с легаси кодом? Зачем всеми любимые wtf-ы из javascript тащить в плюсы?!

BFE>·>А какой вариант красивее?

BFE>Не знаю. Пока ничего красивого в голову не приходит. Если какое-то значение надо преобразовать в значение из enum, то в каждом случае это отдельная функция с проверкой входного значения, постусловиями зависящими от значений enum и, возможно, с бросанием исключения... Так что унифицированная функция вряд ли нужна. Возможно должна получится конструкция вроде:
BFE>
BFE>auto enum_x = toEnum<1_x -> SomeEnumeName::one, 2_x -> SomeEnumeName::two, default_x -> []{ return SomeEnumeName::undefined; }>(x);
BFE>

BFE>но в рамках C++14, с которым я сейчас работаю, это красиво не написать, наверное.
Непонятно накой так извращаться. Хоть обычный switch-case и то красивее будет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[11]: operator* для enum class
От: B0FEE664  
Дата: 24.09.21 16:13
Оценка:
Здравствуйте, ·, Вы писали:

·>'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*.

В чём отличие по семантике для '+'?

BFE>>Каждая лямбда — это отдельный тип.

·>Семантически другой тип. Разница есть. Например, тип — анонимный и с другой областью видимости.
Убедили.

·>Какой? Как лучше назвать функцию?

К enum у меня куча вопросов и это один из них.

·>Это не так важно. Ибо если имя было выбрано неудачно, можно легко переименовать. Притом нередко IDE это сделает на раз, автоматически. С оператором сложнее.

Зависит от проекта. Как только библиотека передаётся в использование другой команде переименовать что-либо становится крайне сложно.

·>Я честно говоря, не очень понял смысл + в той конструкции...

Вот-вот. Не так-то это просто.

·>Почему нельзя какой-нибудь явный cast использовать для работы с легаси кодом?

Так std::chrono::milliseconds(A::TIMEOUT) и есть "каст".

·>Зачем всеми любимые wtf-ы из javascript тащить в плюсы?!

Э, нет! Это приколы C++.

·>Непонятно накой так извращаться. Хоть обычный switch-case и то красивее будет.

Сейчас так и есть: 5 ламбд (со switch-case внутри) в начале функции, а потом 5 их вызовов в конце в конце функции. Так себе решение.
И каждый день — без права на ошибку...
Re[12]: operator* для enum class
От: · Великобритания  
Дата: 24.09.21 16:41
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>·>'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*.

BFE>В чём отличие по семантике для '+'?
+ это арифметическая операция. Мне непонятно как арифметика относится к енумам.

BFE>·>Какой? Как лучше назвать функцию?

BFE>К enum у меня куча вопросов и это один из них.
Ок. Мой ответ — не использовать operator для enum.

BFE>·>Это не так важно. Ибо если имя было выбрано неудачно, можно легко переименовать. Притом нередко IDE это сделает на раз, автоматически. С оператором сложнее.

BFE>Зависит от проекта. Как только библиотека передаётся в использование другой команде переименовать что-либо становится крайне сложно.
Объявляешь obsolete и делаешь новую. Потом уведомляешь другую команду об изменении и даёшь знать когда obsolete подлежит удалению.
С оператором проще точно не будет.

BFE>·>Зачем всеми любимые wtf-ы из javascript тащить в плюсы?!

BFE>Э, нет! Это приколы C++.
Ах.. ясно. Мда уж.

BFE>·>Непонятно накой так извращаться. Хоть обычный switch-case и то красивее будет.

BFE>Сейчас так и есть: 5 ламбд (со switch-case внутри) в начале функции, а потом 5 их вызовов в конце в конце функции. Так себе решение.
Может и можно сделать по-другому, но это имхо самый простой и читаемый вариант.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[13]: operator* для enum class
От: B0FEE664  
Дата: 30.09.21 14:29
Оценка:
Здравствуйте, ·, Вы писали:

BFE>>·>'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*.

BFE>>В чём отличие по семантике для '+'?
·>+ это арифметическая операция. Мне непонятно как арифметика относится к енумам.
Есть две "арифметики", которые относятся к енумам. Первая, традиционная для C/C++: каждому элементу перечисления сопоставляется целое число. Вторая, которой очень не хватает в С++, работает с порядковым номером элемента перечисления. Природа первых и вторых чисел полностью различна, хотя сами числа могут совпадать. Отчасти поэтому ваше предложение назвать функцию преобразования asOrdinal выглядит неоднозначно. Обычно, когда работают с ординалами перечисления используют операторы ++ и --.

Теперь насчёт оператора *.
Для указателя это операция взятия значения.
Почему для элемента перечисления операция взятия значения не может быть выражена этим же оператором?

BFE>>·>Какой? Как лучше назвать функцию?

BFE>>К enum у меня куча вопросов и это один из них.
·>Ок. Мой ответ — не использовать operator для enum.
Конечно логичнее бы было использовать методы enum'а, но их пока не завезли. Можно, конечно, навелосипедить, но элегантно и безошибочно это выглядеть не будет.
И каждый день — без права на ошибку...
Re[14]: operator* для enum class
От: · Великобритания  
Дата: 30.09.21 16:25
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>>>·>'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*.

BFE>>>В чём отличие по семантике для '+'?
BFE>·>+ это арифметическая операция. Мне непонятно как арифметика относится к енумам.
BFE>Есть две "арифметики", которые относятся к енумам. Первая, традиционная для C/C++: каждому элементу перечисления сопоставляется целое число.
Каким боком это арифметика? Это преобразование типа, притом "много типов" (разные енумы) к одному (int). Т.е. теряется инфа о типе.

BFE>Вторая, которой очень не хватает в С++, работает с порядковым номером элемента перечисления. Природа первых и вторых чисел полностью различна, хотя сами числа могут совпадать. Отчасти поэтому ваше предложение назвать функцию преобразования asOrdinal выглядит неоднозначно. Обычно, когда работают с ординалами перечисления используют операторы ++ и --.

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

BFE>Теперь насчёт оператора *.

BFE>Для указателя это операция взятия значения.
BFE>Почему для элемента перечисления операция взятия значения не может быть выражена этим же оператором?
Не очень понятно почему порядковый номер можно считать значением енума.

BFE>·>Ок. Мой ответ — не использовать operator для enum.

BFE>Конечно логичнее бы было использовать методы enum'а, но их пока не завезли. Можно, конечно, навелосипедить, но элегантно и безошибочно это выглядеть не будет.
Зачем методы? Методы хороши если нужно обращение к приватным данным объекта. Чем внешняя функция не угодила?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[15]: operator* для enum class
От: B0FEE664  
Дата: 01.10.21 11:53
Оценка:
Здравствуйте, ·, Вы писали:

BFE>>>>·>'->' для указателей полностью совпадает по семантике. Чего не скажешь про +*.

BFE>>>>В чём отличие по семантике для '+'?
BFE>>·>+ это арифметическая операция. Мне непонятно как арифметика относится к енумам.
BFE>>Есть две "арифметики", которые относятся к енумам. Первая, традиционная для C/C++: каждому элементу перечисления сопоставляется целое число.
·>Каким боком это арифметика? Это преобразование типа, притом "много типов" (разные енумы) к одному (int). Т.е. теряется инфа о типе.
Разным. Кто-то использует как флаги, кто-то как константы...
Или вот пример из стандарта:
namespace std {
enum class byte : unsigned char {};
...

Там и операторы прилагаются.

BFE>>Вторая, которой очень не хватает в С++, работает с порядковым номером элемента перечисления. Природа первых и вторых чисел полностью различна, хотя сами числа могут совпадать. Отчасти поэтому ваше предложение назвать функцию преобразования asOrdinal выглядит неоднозначно. Обычно, когда работают с ординалами перечисления используют операторы ++ и --.

·>Не понял. asOrdinal преобразует enum в его номер. А дальше делай что хочешь с обычным интом.
Разумно предположить, что номер и значение — это два разных числа:
enum class Color : std::uint32_t
{
  red   = 0xFF0000,
  green = 0x00FF00,
  blue  = 0x0000FF
};

assert(asOrdinal(Color::red  ) == 0);
assert(asOrdinal(Color::green) == 1);
assert(asOrdinal(Color::blue ) == 2);

assert(asValue(Color::red  ) == 0xFF0000);
assert(asValue(Color::green) == 0x00FF00);
assert(asValue(Color::blue ) == 0x0000FF);


BFE>>Теперь насчёт оператора *.

BFE>>Для указателя это операция взятия значения.
BFE>>Почему для элемента перечисления операция взятия значения не может быть выражена этим же оператором?
·>Не очень понятно почему порядковый номер можно считать значением енума.
см. выше.

BFE>>·>Ок. Мой ответ — не использовать operator для enum.

BFE>>Конечно логичнее бы было использовать методы enum'а, но их пока не завезли. Можно, конечно, навелосипедить, но элегантно и безошибочно это выглядеть не будет.
·>Зачем методы? Методы хороши если нужно обращение к приватным данным объекта. Чем внешняя функция не угодила?
Значение переменной типа Color — это значение одно из: Color::red, Color::green, Color::blue;
а вот числовое значение (как и номер) — это уже свойство каждого из значений. Свойства принято оформлять методами, а не внешними функциями.
И каждый день — без права на ошибку...
Re[16]: operator* для enum class
От: · Великобритания  
Дата: 01.10.21 15:53
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>·>Каким боком это арифметика? Это преобразование типа, притом "много типов" (разные енумы) к одному (int). Т.е. теряется инфа о типе.

BFE>Разным. Кто-то использует как флаги, кто-то как константы...
BFE>Или вот пример из стандарта:
Я имею в виду, что можно привести enum1->int, enum2->int а обратно — уже нельзя без явного указания типа.

BFE>>>Вторая, которой очень не хватает в С++, работает с порядковым номером элемента перечисления. Природа первых и вторых чисел полностью различна, хотя сами числа могут совпадать. Отчасти поэтому ваше предложение назвать функцию преобразования asOrdinal выглядит неоднозначно. Обычно, когда работают с ординалами перечисления используют операторы ++ и --.

BFE>·>Не понял. asOrdinal преобразует enum в его номер. А дальше делай что хочешь с обычным интом.
BFE>Разумно предположить, что номер и значение — это два разных числа:
Эээ.. ну да. Я думал тебе и нужен номер. А так верно — можно иметь две функции asOrdinal и asValue. С операторами — бардак, неясно какой оператор чему должен соответствовать. Когда у тебя явное имя функции — всё чётко и понятно.

BFE>·>Не очень понятно почему порядковый номер можно считать значением енума.

BFE>см. выше.
Ну да, видимо мы говорили о разных вещах. Но даже и так — выдать числовое значение енума и выдать адресуемое указателем данное — как-то не очень похожи семантически.

BFE>>>Конечно логичнее бы было использовать методы enum'а, но их пока не завезли. Можно, конечно, навелосипедить, но элегантно и безошибочно это выглядеть не будет.

BFE>·>Зачем методы? Методы хороши если нужно обращение к приватным данным объекта. Чем внешняя функция не угодила?
BFE>Значение переменной типа Color — это значение одно из: Color::red, Color::green, Color::blue;
BFE>а вот числовое значение (как и номер) — это уже свойство каждого из значений. Свойства принято оформлять методами, а не внешними функциями.
"содержит ли строка 'foo'" — это тоже свойство каждого из значений строки. Запихаем метод "hasFoo()" в String?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[7]: operator* для enum class
От: Максим Россия  
Дата: 21.10.21 07:14
Оценка:
R>Когда ты определяешь лямбду внутри функции с формальным параметром auto, ты фактически определяешь локальный класс с шаблонным оператором operator(). На обычных классах это сделать невозможно, потому что определение шаблонов внутри функции (любых) запрещено.

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

auto foo() {
    auto lambda = [](auto i) { std::cout << i; };
    lambda(5);

    return 5;
}
Errare humanum est
Re[8]: operator* для enum class
От: night beast СССР  
Дата: 21.10.21 07:23
Оценка: 4 (1)
Здравствуйте, Максим, Вы писали:

R>>Когда ты определяешь лямбду внутри функции с формальным параметром auto, ты фактически определяешь локальный класс с шаблонным оператором operator(). На обычных классах это сделать невозможно, потому что определение шаблонов внутри функции (любых) запрещено.


М>Сергей, не могли бы Вы более подробнее объяснить что тут имеется ввиду. Вот такой код вроде нормально работает


твой работает, а этот нет:
auto foo() {
    struct Lambda {
        template<typename T>
        void operator()(T); // внутри функции так нельзя
    };
    Lambda{}(5);
    return 5
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.