Re[12]: Как записать такое в современном C++?
От: so5team https://stiffstream.com
Дата: 30.07.24 15:33
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

S>>А если не повторяются?


ЕМ>Тогда там везде разная логика обработки.


Спасибо, Кэп. Вопрос был не в этом.

ЕМ>И внести ошибку, забыв добавить к сравнению одно из значений, или добавив не то, что нужно, не сложнее, чем сделать опечатку.


Сложнее. Семантическая (да и синтаксическая) нагрузка разная.

S>>вы все никак не можете смириться с той вселенной, в которой живете?


ЕМ>А Вы действительно воображаете, будто это "вселенная", а не просто засилье подхода "делаем потому, что можем"?


Я не воображаю, я это ощущаю как данность: в этой вселенной мы имеем тот C++, который смогли сделать. Хотели разные люди разного, предлагали и рекламировали разное, даже реализовывали в компиляторах в качестве расширений разное. А в итоге имеем то, что имеем. Потому, что другого не смогли.

S>>у вас нужно попросить объяснить, почему спаггети-стайл, и почему в макросах. Если не сможете, то надавать по рукам.


ЕМ>Тут весь вопрос в том, что понимается под "сможете".


То и понимаете: сможете ли объяснить так, что другие члены команды сочтут ваши объяснения достаточными. Или же останетесь на уровне "мне так удобнее".

Хотя о чем это я? Где вы, и где команды.

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


А если не бредить общими словами и показать пример? Ну типа вот на макросах, а вот на тех же принципах на шаблонах?

S>>Спич как раз о том, что не нужно требовать от инструмента того, на что он не рассчитан.


ЕМ>То есть, STL, Boost, Loki применяют инструмент именно для того, на что он был рассчитан?


STL, Boost и Loki -- это сами инструменты. И да, они используют базовый C++ именно для того, на что он был рассчитан.

EM>А в последнем обсуждаемом примере одноразовый шаблонный класс создается тоже для того, на что была рассчитана идея классов?


Во-первых, он не одноразовый.

Во-вторых, да, там используется идея шаблона класса.

S>>Тов.B0FEE664 привел пример кода, который решает его задачи. На универсальность не претендует.


ЕМ>Из высказываний тов. B0FEE664 следует как раз обратное.


Цитату можно?

S>>Так чего вы к этому коду прицепились?


ЕМ>Того, что писать такой код поощряет уродливый механизм реализации "современных" возможностей шаблонов, выдаваемый за передовой.


Если вы не смогли этот механизм освоить, то это не значит что:

a) он уродливый;
b) он что-то поощряет или нет;
c) он кем-то выдается за передовой.

Человек сделал так, как ему удобно. Результат понятен. Как пользоваться тоже понятно. Цель, можно сказать, достигнута.

S>>Пишите как можете. C++ позволяет делать одно и тоже кучей разных способов.


ЕМ>Так я всегда пишу, как могу, но C++ постоянно вынуждает делать вроде бы простые вещи непременно через задницу.


Без примеров нещитово.
Re[12]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 30.07.24 16:33
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>Вот ввели enum class и что? 90% программистов продолжают прописывать значения элементам и кастить.

ЕМ>Теперь это их вина, а не создателей стандартов и компиляторов. У тех, кто имеет доступ к рычагам воздействия, есть выбор — заставлять или не обращать внимания.
Но какой тогда смысл в enum class?

BFE>>Если запретить прописывать значения, то почти все из них просто перестанет пользоваться перечислением.

ЕМ>А зачем запрещать-то?
Чтобы не было соблазна их использовать.

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

Зачем перечислению значения?
И каждый день — без права на ошибку...
Re[13]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 30.07.24 16:39
Оценка:
Здравствуйте, so5team, Вы писали:

ЕМ>>И внести ошибку, забыв добавить к сравнению одно из значений, или добавив не то, что нужно, не сложнее, чем сделать опечатку.


S>Сложнее. Семантическая (да и синтаксическая) нагрузка разная.


Я уже подчеркивал, что бороться нужно в первую очередь с теми ошибками, которые наиболее вероятны (и в среднем, и в конкретных условиях), а не получили наибольшую известность по тем или иным причинам. Большинство же продолжает опасаться того, о чем больше говорят и пишут, а не того, что наиболее вероятно у них самих.

S>Ну типа вот на макросах, а вот на тех же принципах на шаблонах?


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

S>STL, Boost и Loki -- это сами инструменты. И да, они используют базовый C++ именно для того, на что он был рассчитан.


Где можно почитать о том, как в C++ рассчитывали на использование побочных эффектов шаблонов?

EM>>А в последнем обсуждаемом примере одноразовый шаблонный класс создается тоже для того, на что была рассчитана идея классов?


S>Во-первых, он не одноразовый.


В том виде, в каком его применяет автор — одноразовый.

S>Во-вторых, да, там используется идея шаблона класса.


А зачем там класс? По-хорошему, здесь нужен просто шаблон функции.

S>>>Тов.B0FEE664 привел пример кода, который решает его задачи. На универсальность не претендует.


ЕМ>>Из высказываний тов. B0FEE664 следует как раз обратное.


S>Цитату можно?


"Для меня этот код не частный, а наоборот, слишком общий...
Автор: B0FEE664
Дата: 29.07.24
"

S>Если вы не смогли этот механизм освоить


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

ЕМ>>C++ постоянно вынуждает делать вроде бы простые вещи непременно через задницу.


S>Без примеров нещитово.


Тут уже кучу примеров навалили, Вам мало? Поскольку Вам они кажутся вполне себе логичными и даже изящными, какой смысл приводить дополнительные?

Знаете, это весьма похоже на "развитие современного искусства". Еще не так давно оставались хоть какие-то опорные точки, позволяющие отличить шедевр от говнища, но теперь все определяется исключительно мнением активного большинства. Даже если численно оно будет абсолютным меньшинством, именно его активность, громкость и упорство позволят признать "шедевром" все, что угодно.
Re[13]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 30.07.24 17:01
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>какой тогда смысл в enum class?


Прежде всего — в инкапсуляции идентификаторов в enum. А уж как там заданы значения — уже второй вопрос.

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

BFE>Зачем перечислению значения?


Для случаев, когда какие-то значения имеют особый смысл. Простейший случай — выделить группы (варианты успешного завершения, предупреждения, ошибки и т.п.). Да, придется закладываться на предельный размер диапазона, но иначе-то еще менее удобно.

Еще в ряде случаев полезно иметь значения, имеющие в младших разрядах уникальные последовательные номера, но с возможным добавлением дополнительных старших разрядов в качестве признаков. Через enum такого не сделать — приходится выписывать пачки обычных определений, вручную следя за монотонным возрастанием номеров. Ежли кто добавит новый элемент в середину, не перенумеровав остальные — будет грустно.
Re[14]: Как записать такое в современном C++?
От: kov_serg Россия  
Дата: 30.07.24 17:21
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, B0FEE664, Вы писали:


BFE>>какой тогда смысл в enum class?

ЕМ>Прежде всего — в инкапсуляции идентификаторов в enum. А уж как там заданы значения — уже второй вопрос.
ЕМ>Кстати, отсутствие автоматического определения количества элементов, наименьшего и наибольшего значения в enum — тоже очевидный недостаток.

Так и раньше ни кто не запрещал идентификаторы запихивать внутрь класса вместе с доп. информацией
struct E {
  enum { C0,C1,C2, C_MAX };
  static const char* to_chars(int id) {
    switch(id) {
    case C0: return "C0";
    case C1: return "C1";
    case C2: return "C2";
    }
    return 0;
  }
  static int count() { return C_MAX; }
  static int min() { return C0; }
  static int max() { return C_MAX-1; }
};

struct B {
  enum { B1=1,B2=2,B3=4, B_MASK=B1|B2|B3 };
  static void fmt(int v, void (*write)(void* ctx,const char* text), void *ctx) {
    if (v&B1) write(ctx,"B1");
    if (v&B2) write(ctx,"B2");
    if (v&B3) write(ctx,"B3");
  }
  static int mask() { return B_MASK; };
};



ЕМ>Еще в ряде случаев полезно иметь значения, имеющие в младших разрядах уникальные последовательные номера, но с возможным добавлением дополнительных старших разрядов в качестве признаков. Через enum такого не сделать — приходится выписывать пачки обычных определений, вручную следя за монотонным возрастанием номеров. Ежли кто добавит новый элемент в середину, не перенумеровав остальные — будет грустно.
Re[14]: Как записать такое в современном C++?
От: so5team https://stiffstream.com
Дата: 30.07.24 18:49
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>И внести ошибку, забыв добавить к сравнению одно из значений, или добавив не то, что нужно, не сложнее, чем сделать опечатку.


S>>Сложнее. Семантическая (да и синтаксическая) нагрузка разная.


ЕМ>Я уже подчеркивал, что бороться нужно в первую очередь с теми ошибками, которые наиболее вероятны (и в среднем, и в конкретных условиях)


Да что вы говорите?!

А тяжесть последствий от ошибки оценивать вообще не нужно?

А стоимость устранения? Например, есть класс ошибок X, стоимость устранения этого класса 1 человеко-час на весь проект. Т.е. даже не копейки, а доли копейки. Полагаю, класс ошибок X нужно вообще не рассматривать, т.к. их вероятность ниже какого-то порога.

Отлично, Евгений, отлично. Жгите. Вы можете, я верю.

ЕМ>Большинство же продолжает опасаться того, о чем больше говорят и пишут, а не того, что наиболее вероятно у них самих.


Какое большинство, актитесь. Вы в одиночку пишете код в который считанные единицы заглядывают. Откуда у вас знания о "большинстве"? Из обсуждений на RSDN-е?

S>>Ну типа вот на макросах, а вот на тех же принципах на шаблонах?


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


Т.е. конкретных примеров не будет? Мне нужно перелопачивать все это обсуждение и выискивать примеры самостоятельно?

S>>STL, Boost и Loki -- это сами инструменты. И да, они используют базовый C++ именно для того, на что он был рассчитан.


ЕМ>Где можно почитать о том, как в C++ рассчитывали на использование побочных эффектов шаблонов?


Позволю себе ответить вопросом на вопрос: а что, STL, Boost и Loki базируются на побочных эффектах шаблонов? С примерами, пожалуйста. Это во-первых.

Во-вторых, ну вот есть некие побочные эффекты. Вполне себе легальный способ. Другого нет. Может быть когда-нибудь в будущем что-то будет, может быть нет. Зачем отказываться и не использовать то что есть здесь и сейчас, если это решает задачу наилучшим образом?

У меня есть всего две причины, которые для меня самого временами актуальны:

1) сложность кода превышает способности даже самых опытных и продвинутых членов команды;
2) сложность кода ведет к крахам компиляторов с internal compiler error.

Если эти причины не актуальны, то зачем игнорировать?

Всяко лучше, чем базироваться на нестандартных расширениях от Microsoft.

EM>>>А в последнем обсуждаемом примере одноразовый шаблонный класс создается тоже для того, на что была рассчитана идея классов?


S>>Во-первых, он не одноразовый.


ЕМ>В том виде, в каком его применяет автор — одноразовый.


У вас явно свои представления об "одноразовости". Сам автор привел несколько примеров использования. Если это для вас "одноразовый", то на RSDN-е вам не помогут.

S>>Во-вторых, да, там используется идея шаблона класса.


ЕМ>А зачем там класс? По-хорошему, здесь нужен просто шаблон функции.


Мы не видим всех сценариев использования.

S>>>>Тов.B0FEE664 привел пример кода, который решает его задачи. На универсальность не претендует.


ЕМ>>>Из высказываний тов. B0FEE664 следует как раз обратное.


S>>Цитату можно?


ЕМ>"Для меня этот код не частный, а наоборот, слишком общий...
Автор: B0FEE664
Дата: 29.07.24
"


Ну так перечитайте. Автор пишет, что класс общий, потому, что допускает даже такие сравнения, на которые сам автор не рассчитывал. Универсальности нет, т.к. все сценарии использования в рамках одной и той же задачи -- проверить, входит ли текущее значение в список предопределенных значений.

S>>Если вы не смогли этот механизм освоить


ЕМ>Я не хочу его осваивать, он вызывает у меня отвращение


Да фиолетово что вы хотите. Есть инструмент со своими качествами и возможностями. Этот инструмент можно освоить и применять там, где это выгодно. Либо можно ныть на RSDN-е о том, как вокруг все коряво и убого.

ЕМ>>>C++ постоянно вынуждает делать вроде бы простые вещи непременно через задницу.


S>>Без примеров нещитово.


ЕМ>Тут уже кучу примеров навалили, Вам мало? Поскольку Вам они кажутся вполне себе логичными и даже изящными, какой смысл приводить дополнительные?


Можете привести пример и сказать "вот здесь плохо потому-то и потому-то?"
Если можете, тогда будет что обсуждать.

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

ЕМ>Знаете, это весьма похоже на "развитие современного искусства".


Завязывали бы вы с бла-бла-бла.
Re[14]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 31.07.24 14:27
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

BFE>>какой тогда смысл в enum class?

ЕМ>Прежде всего — в инкапсуляции идентификаторов в enum. А уж как там заданы значения — уже второй вопрос.
namespace Machine
{
enum Mode
{
  eAuto, eManual
};
}
typedef Machine::Mode MachineMode;



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

Вроде бы (ещё не дочитал), это собираются, наконец, сделать.

BFE>>Зачем перечислению значения?

ЕМ>Для случаев, когда какие-то значения имеют особый смысл. Простейший случай — выделить группы (варианты успешного завершения, предупреждения, ошибки и т.п.). Да, придется закладываться на предельный размер диапазона, но иначе-то еще менее удобно.
Что ещё за "предельный размер диапазона"?

ЕМ>Еще в ряде случаев полезно иметь значения, имеющие в младших разрядах уникальные последовательные номера, но с возможным добавлением дополнительных старших разрядов в качестве признаков. Через enum такого не сделать — приходится выписывать пачки обычных определений, вручную следя за монотонным возрастанием номеров. Ежли кто добавит новый элемент в середину, не перенумеровав остальные — будет грустно.


Пожалуйста, ответьте не на вопрос: какое отношение это имеет к перечислению?
И каждый день — без права на ошибку...
Re[15]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 31.07.24 14:46
Оценка:
Здравствуйте, B0FEE664, Вы писали:

ЕМ>>Прежде всего — в инкапсуляции идентификаторов в enum.

BFE>
BFE>namespace Machine
BFE>enum Mode
BFE>


Ну коряво же. Давайте еще вспомним, что в раннем C имена полей структур тоже были глобальными, и починили это чуть ли не после появления C++. Может, Страуструпу не нужно было ограничивать область видимости членов класса, нехай бы все были в глобальной?

BFE>Что ещё за "предельный размер диапазона"?


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

BFE>какое отношение это имеет к перечислению?


Прямое. Перечисление лежит в основе создания констант, а явное задание значений позволяет в отдельных случаях отступать от этого порядка. Если [почти] все константы имеют явно заданные значения, то и не стоит их определять в enum.

Если бы enum изначально был похож на паскалевский перечислимый тип, давал возможность узнавать количество элементов и создавать множества, я бы не стал требовать от него явного задания значений. Но раз уж его реализовали в виде примитивного средства с дополнительными возможностями, то грех не пользоваться.
Re[16]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 31.07.24 15:01
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>Прежде всего — в инкапсуляции идентификаторов в enum.

BFE>>
BFE>>namespace Machine
BFE>>enum Mode
BFE>>


ЕМ>Ну коряво же.

Почему?

ЕМ>Давайте еще вспомним, что в раннем C имена полей структур тоже были глобальными, и починили это чуть ли не после появления C++. Может, Страуструпу не нужно было ограничивать область видимости членов класса, нехай бы все были в глобальной?

Давайте. Что делать, если в двух библиотеках совпадают названия (но не элементы) у enum class?

BFE>>какое отношение это имеет к перечислению?

ЕМ>Прямое. Перечисление лежит в основе создания констант, а явное задание значений позволяет в отдельных случаях отступать от этого порядка. Если [почти] все константы имеют явно заданные значения, то и не стоит их определять в enum.
Вообще-то в основе создания констант лежит #define

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

Судя по предыдущему абзацу и улыбке — стали бы.

ЕМ> Но раз уж его реализовали в виде примитивного средства с дополнительными возможностями, то грех не пользоваться.

То есть использовать перечисления для констант — это не грех (несмотря на то, что ключевое слово const существует довольно давно), а использовать SFINAE — грех? Не находите, что это не последовательная позиция?
И каждый день — без права на ошибку...
Re[17]: Как записать такое в современном C++?
От: kov_serg Россия  
Дата: 31.07.24 15:18
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>То есть использовать перечисления для констант — это не грех (несмотря на то, что ключевое слово const существует довольно давно), а использовать SFINAE — грех? Не находите, что это не последовательная позиция?

Ваш const не совсем const, поэтому и используют другие способы
int fn(int i) {
  const int c1=1;
  enum { c2=2 };
  switch(i) {
  //case c1: return c1; // error: label does not reduce to an integer constant
  case c2: return c2;
  }
  return 0;
}
Re[17]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 31.07.24 16:08
Оценка:
Здравствуйте, B0FEE664, Вы писали:

ЕМ>>Ну коряво же.

BFE>Почему?

Потому, что enum создает группу идентификаторов, объединенных общей идеей, а следовательно — областью видимости, пусть и неявной. Никто ж не создает {One, Two, Three}. Почему в обсуждаемом примере все идентификаторы начинаются на E?

BFE>Что делать, если в двух библиотеках совпадают названия (но не элементы) у enum class?


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

BFE>Вообще-то в основе создания констант лежит #define


Вообще-то это не "константы", а "макроопределения". Это делалось (и посейчас нередко делается) исключительно от нехватки языковых средств.

BFE>То есть использовать перечисления для констант — это не грех (несмотря на то, что ключевое слово const существует довольно давно)


Когда const только появилось, большинство компиляторов понимало его исключительно в смысле "неизменяемый объект", и даже при максимальной оптимизации не всегда заменяло на литеральную константу. Заменять всегда стали лишь где-то в середине 90-х, если не ошибаюсь.

BFE>использовать SFINAE — грех?


Конечно, использовать SFINAE для выбора наиболее общего варианта шаблона — не грех, оно для этого и создавалось. И даже использовать SFINAE в сочетании с трюками, возможность которых изначально не закладывалась в механизм — тоже не грех, если это делается или для демонстрации забавного эффекта, или сугубо для себя, или сугубо временно, в ожидании реализации соответствующих функций в компиляторах. А вот делать такие трюки нормой жизни, да еще рекомендовать их для изучения, освоения и повсеместного применения — не простой грех, а очень тяжкий. Подход называется "ну ведь получилось же, и работает, какие претензии?".
Re[18]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 31.07.24 16:11
Оценка:
Здравствуйте, kov_serg, Вы писали:

BFE>>То есть использовать перечисления для констант — это не грех (несмотря на то, что ключевое слово const существует довольно давно), а использовать SFINAE — грех? Не находите, что это не последовательная позиция?

_>Ваш const не совсем const, поэтому и используют другие способы
А он не мой, это не я стандарт писал.
И каждый день — без права на ошибку...
Re[18]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 31.07.24 16:21
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>Ну коряво же.

BFE>>Почему?
ЕМ>Потому, что enum создает группу идентификаторов, объединенных общей идеей, а следовательно — областью видимости, пусть и неявной. Никто ж не создает {One, Two, Three}.
И для этого они лежат в namespace.

ЕМ> Почему в обсуждаемом примере все идентификаторы начинаются на E?

Предполагаю, что это сокращение от слова ERROR.

BFE>>Что делать, если в двух библиотеках совпадают названия (но не элементы) у enum class?

ЕМ>То же самое, как если совпадают имена классов, глобальных переменных, функций. Почему enum должен выбиваться из этой схемы?
Вот если их поместить в отдельный namespace, то они и не будут выбиваться из схемы (раз уж изначально это не было сделано)

BFE>>Вообще-то в основе создания констант лежит #define

ЕМ>Вообще-то это не "константы", а "макроопределения". Это делалось (и посейчас нередко делается) исключительно от нехватки языковых средств.
Согласен. Но это никак не отменяет, что использовать #define для констант уместнее, чем enum.

BFE>>использовать SFINAE — грех?

ЕМ>Конечно, использовать SFINAE для выбора наиболее общего варианта шаблона — не грех, оно для этого и создавалось. И даже использовать SFINAE в сочетании с трюками, возможность которых изначально не закладывалась в механизм — тоже не грех, если это делается или для демонстрации забавного эффекта, или сугубо для себя, или сугубо временно, в ожидании реализации соответствующих функций в компиляторах. А вот делать такие трюки нормой жизни, да еще рекомендовать их для изучения, освоения и повсеместного применения — не простой грех, а очень тяжкий. Подход называется "ну ведь получилось же, и работает, какие претензии?".

Вот сейчас уже есть нормальные константы. Вы перестали использовать перечисления для того, чтобы задавать константы?
И каждый день — без права на ошибку...
Re[19]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 31.07.24 16:35
Оценка:
Здравствуйте, B0FEE664, Вы писали:

ЕМ>>Потому, что enum создает группу идентификаторов, объединенных общей идеей


BFE>И для этого они лежат в namespace.


Тогда почему там не лежат члены классов?

ЕМ>>Почему в обсуждаемом примере все идентификаторы начинаются на E?


BFE>Предполагаю, что это сокращение от слова ERROR.


А зачем нужен такой префикс? Уникальность обеспечивается и без него.

BFE>Вот если их поместить в отдельный namespace, то они и не будут выбиваться из схемы (раз уж изначально это не было сделано)


Изначально, напомню, инкапсуляции не было и для полей структур. Ее тоже зря сделали?

BFE>использовать #define для констант уместнее, чем enum.


Я бы сказал, что уместнее использовать [static] const, а при невозможности — #define. Но это для разрозненных констант, от которых не ожидается какой-либо регулярности. Если же константы хотя бы в основе завязаны на перечисление, то вполне логично определять их в перечислении.

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


Я ж говорил, что для "просто констант" давно использую [static] const. Но, если мне нужны константы, например, для кодов ошибок, разделенных на группы (по степени серьезности, или по ситуациям, по связанным объектам и т.п.), то альтернативой enum будет только ручной инкремент. Вы предлагаете использовать его?

Если Вы до сих пор пытаетесь провести аналогию с шаблонными трюками, то это ж несопоставимые вещи. enum — простая конструкция, ее смысл очевиден любому, кто хоть более-менее знаком с языком. Она не порождает отдаленных последствий. Ну и то, что в языке таки появился enum class, уже говорит о том, что проблему осознали, и приняли меры для ее устранения. А что появилось в языке для замены шаблонной магии? Даже if constexpr можно применить только к исполняемому коду. Это не метапрограммирование, а издевательство.
Re[18]: Как записать такое в современном C++?
От: so5team https://stiffstream.com
Дата: 31.07.24 16:56
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Ваш const не совсем const, поэтому и используют другие способы

_>
_>int fn(int i) {
_>  const int c1=1;
_>  enum { c2=2 };
_>  switch(i) {
_>  //case c1: return c1; // error: label does not reduce to an integer constant
_>  case c2: return c2;
_>  }
_>  return 0;
_>}
_>


А речь точно идет о C++?

https://wandbox.org/permlink/RWneePV7jikXCdQy
Re[19]: Как записать такое в современном C++?
От: kov_serg Россия  
Дата: 31.07.24 17:15
Оценка: +1
Здравствуйте, so5team, Вы писали:

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


_>>Ваш const не совсем const, поэтому и используют другие способы

_>>
_>>int fn(int i) {
_>>  const int c1=1;
_>>  enum { c2=2 };
_>>  switch(i) {
_>>  //case c1: return c1; // error: label does not reduce to an integer constant
_>>  case c2: return c2;
_>>  }
_>>  return 0;
_>>}
_>>


S>А речь точно идет о C++?


S>https://wandbox.org/permlink/RWneePV7jikXCdQy


А теперь представьте что константы надо объявить в header-е
extern const int a;
const int b=1;

const int a=0;

И всё приплыли. А enum-ы можно объявлять где попало и они constexpr. Правда использование таких констант в шаблонах немного не удобно. Но это проблемы шаблонов, а не констант.
Re[20]: Как записать такое в современном C++?
От: B0FEE664  
Дата: 31.07.24 18:37
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>>>Потому, что enum создает группу идентификаторов, объединенных общей идеей

BFE>>И для этого они лежат в namespace.
ЕМ>Тогда почему там не лежат члены классов?
Потому, что их объединение производится через class

ЕМ>>>Почему в обсуждаемом примере все идентификаторы начинаются на E?

BFE>>Предполагаю, что это сокращение от слова ERROR.
ЕМ>А зачем нужен такой префикс?
Чтобы показать, что всё это коды ошибок.

ЕМ>Уникальность обеспечивается и без него.

Ни с префиксом, ни без префикса уникальность не обеспечивается.

BFE>>Вот если их поместить в отдельный namespace, то они и не будут выбиваться из схемы (раз уж изначально это не было сделано)

ЕМ>Изначально, напомню, инкапсуляции не было и для полей структур. Ее тоже зря сделали?
Наоборот, делали не зря. Зря не сделали этого с enum и зря перечислениям не запретили присваивать численные значения.

BFE>>использовать #define для констант уместнее, чем enum.

ЕМ>Я бы сказал, что уместнее использовать [static] const, а при невозможности — #define. Но это для разрозненных констант, от которых не ожидается какой-либо регулярности. Если же константы хотя бы в основе завязаны на перечисление, то вполне логично определять их в перечислении.
Нет, не логично. Константы логично объединить в множество или положить в одно scope-пространство, но не в перечисление.

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

ЕМ>Я ж говорил, что для "просто констант" давно использую [static] const.
Почему не constexp ?
  Скрытый текст
#include <iostream>
#include <stdexcept>

 constexpr int next(int n) { return 1 + n; }

 constexpr int asdf = 1;
 constexpr int asdg = next(asdf);
 
int main()
{
   std::cout << '\n';
   std::cout << "asdf = " << asdf;    
   std::cout << '\n';
   std::cout << "asdg = " << asdg;    
   
   
   constexpr int arr[asdg] = {asdf, asdg};
   
   int x = 2;
   switch(x)
   {
      case arr[0]:
          std::cout << '\n' << "arr[0] ";    
      break;
      
      case arr[1]:
          std::cout << '\n' << "arr[1]";    
      break;
   }
   
}


ЕМ>Но, если мне нужны константы, например, для кодов ошибок, разделенных на группы (по степени серьезности, или по ситуациям, по связанным объектам и т.п.), то альтернативой enum будет только ручной инкремент. Вы предлагаете использовать его?

Можно и инкремент, если он вам зачем-то нужен, хотя я с трудом представляю ситуацию, где ТАКОЕ может понадобиться.
Я вообще не понимаю, зачем использовать коды ошибок. У ошибки есть имя — этого достаточно. А код — он может меняться от системы к системе, ну, как в исходном примере, с EAGAIN и EWOULDBLOCK.
Именно поэтому я для ошибок часто использую перечисления и никогда константы. И перечисления я использую именно как перечисления, то есть набор имен и никак не значений.

ЕМ>Если Вы до сих пор пытаетесь провести аналогию с шаблонными трюками, то это ж несопоставимые вещи.

Для меня это то же самое — использование конструкции языка не по назначению.

ЕМ>enum — простая конструкция, ее смысл очевиден любому, кто хоть более-менее знаком с языком. Она не порождает отдаленных последствий.

Да ну? Любому? Да 90% вообще не понимают (включая авторов стандарта), что такое перечисление и вы, похоже, из их числа, раз путаете перечисление с набором констант.

И вообще, попробуйте поспрашивать коллег, что выведет следующий код:
#include <iostream>
enum AB
 {
    a = 1,  
    b = 0xF0000000
};

enum CD
 {
    cd_c = 1,  
    cd_d = 0xF00000000
};
 
 
int main()
{
  if ( sizeof(a) == sizeof(cd_c) )
     std::cout << "yes";
  else     
     std::cout << "no";
}



ЕМ> Ну и то, что в языке таки появился enum class, уже говорит о том, что проблему осознали, и приняли меры для ее устранения.

Нет, не осознали. Даже наоборот: они ввели std::byte.

ЕМ> А что появилось в языке для замены шаблонной магии?

auto

ЕМ> Даже if constexpr можно применить только к исполняемому коду. Это не метапрограммирование, а издевательство.

Метапрограммирование ещё только предлагают, но какое-то некрасивое.
И каждый день — без права на ошибку...
Re[21]: Как записать такое в современном C++?
От: kov_serg Россия  
Дата: 31.07.24 19:53
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>И вообще, попробуйте поспрашивать коллег, что выведет следующий код:

BFE>
BFE>#include <iostream>
BFE>enum AB
BFE> {
BFE>    a = 1,  
BFE>    b = 0xF0000000
BFE>};

BFE>enum CD
BFE> {
BFE>    cd_c = 1,  
BFE>    cd_d = 0xF00000000
BFE>};
 
 
BFE>int main()
BFE>{
BFE>  if ( sizeof(a) == sizeof(cd_c) )
BFE>     std::cout << "yes";
BFE>  else     
BFE>     std::cout << "no";
BFE>}    
BFE>

Да C++ он такой
enum E1 { e1_c1=1 };
enum E2 { e2_c1=1 };

void fn(enum E1 e) { std::cout<<"fn.E1\n"; }
void fn(enum E2 e) { std::cout<<"fn.E2\n"; }
void fn(char e) { std::cout<<"fn.char\n"; }
void fn(signed char e) { std::cout<<"fn.schar\n"; }
void fn(unsigned char e) { std::cout<<"fn.uchar\n"; }
void fn(short e) { std::cout<<"fn.short\n"; }
void fn(int e) { std::cout<<"fn.int\n"; }
void fn(unsigned e) { std::cout<<"fn.uint\n"; }
void fn(long long e) { std::cout<<"fn.llong\n"; }

void test() {
    fn(e1_c1);
    fn(e2_c1);
    fn('\x01');
    fn(+'\x01');
    fn(1);
    fn((char)1);
    fn((unsigned char)1);
    fn((signed char)1);
    fn((short)1);
    fn(1u);
    fn(1LL);
    fn(+e1_c1);
    fn(+e2_c1);
}

fn.E1
fn.E2
fn.char
fn.int
fn.int
fn.char
fn.uchar
fn.schar
fn.short
fn.uint
fn.llong
fn.int
fn.int

Ему мало значения константы, ему надо еще и мозг по выносить.
Отредактировано 31.07.2024 19:58 kov_serg . Предыдущая версия .
Re[21]: Как записать такое в современном C++?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 01.08.24 00:26
Оценка:
Здравствуйте, B0FEE664, Вы писали:

ЕМ>>Тогда почему там не лежат члены классов?


BFE>Потому, что их объединение производится через class


Чем это принципиально отличается от объединения через enum?

ЕМ>>А зачем нужен такой префикс?


BFE>Чтобы показать, что всё это коды ошибок.


На букву E могут начинаться не только идентификаторы кодов ошибок. А если полагать, что идентификатор в верхнем регистре, начинающийся на E — это код ошибки, то что это, если не обособленная группа?

ЕМ>>Уникальность обеспечивается и без него.


BFE>Ни с префиксом, ни без префикса уникальность не обеспечивается.


Я про "локальную уникальность" среди кодов ошибок вида Exxx. Будь enum изначально инкапсулирующий, можно было сразу определить вроде enum ErrorCode { ... };

BFE>зря перечислениям не запретили присваивать численные значения.


Какие неудобства или риски это создает?

Ситуация, кстати, похожа на ту самую подстановку пакета параметров шаблона. Сейчас это возможно только в регулярном, систематическом виде. Если вдруг нужен пакет разнотипных параметров, то или никак, или через вырвиглазные трюки. А будь внутри шаблона возможность работать параметрами по отдельности, так и систематически, это можно было бы применить к более широкому спектру задач.

Так и с enum: его можно применить для создания только систематических, регулярных перечислений, а можно в эту регулярность при необходимости вмешаться. А если б вмешиваться можно было по-разному, объясняя компилятору, как сочетать регулярность с отступлениями от нее, не приходилось бы городить костыли.

BFE>Константы логично объединить в множество или положить в одно scope-пространство, но не в перечисление.


А если во множестве несколько сотен констант, 95% из которых идут подряд, но 5% этот порядок нарушают?

ЕМ>>Я ж говорил, что для "просто констант" давно использую [static] const.

BFE>Почему не constexp ?

Потому, что после VS 2008 я еще не видел столь же удобной и быстрой в работе версии, а компиляторы VS 2008 constexpr еще не знают.

ЕМ>>Но, если мне нужны константы, например, для кодов ошибок, разделенных на группы (по степени серьезности, или по ситуациям, по связанным объектам и т.п.), то альтернативой enum будет только ручной инкремент. Вы предлагаете использовать его?


BFE>Можно и инкремент, если он вам зачем-то нужен, хотя я с трудом представляю ситуацию, где ТАКОЕ может понадобиться.


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

BFE>Я вообще не понимаю, зачем использовать коды ошибок. У ошибки есть имя — этого достаточно.


У ошибки также могут быть и свойства — уровень серьезности, область возникновения и т.п. Например, в виндовом ядре и Win32 32-разрядный код ошибки содержит несколько полей.

BFE>А код — он может меняться от системы к системе, ну, как в исходном примере, с EAGAIN и EWOULDBLOCK.


Да, и это создает приличный геморрой в линуксах, как и необходимость во многих случаях собирать софт под целевую систему. А в винде коды не меняются, они всегда одни и те же в любой системе на базе Win32. И приложение, правильно сделанное под Win95, будет в неизменном виде работать под Win11. На мой взгляд, это более серьезная степень совместимости, нежели на уровне исходников.

BFE>Именно поэтому я для ошибок часто использую перечисления и никогда константы. И перечисления я использую именно как перечисления, то есть набор имен и никак не значений.


В идеальном перечислении было бы удобно иметь возможность задавать правила присвоения значений константам. Тогда можно было бы выбирать как простое перечисление, так и более сложное, но все равно систематическое. То же самое можно было бы сделать, будь в языке макропроцессор с псевдоциклами. Без этого какие-то варианты можно реализовать только шаблонными трюками.

BFE>Для меня это то же самое — использование конструкции языка не по назначению.


Что значит "не по назначению"? Для enum изначально была заявлена возможность явного задания значений, а возможность шаблонных трюков была открыта случайно.

BFE>Да 90% вообще не понимают (включая авторов стандарта), что такое перечисление и вы, похоже, из их числа, раз путаете перечисление с набором констант.


И что же такое перечисление? А главное — из чего следует именно такая его природа, а не иная?

BFE>
BFE>    cd_d = 0xF00000000
BFE>


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

BFE>они ввели std::byte.


Ну, не слишком удачная попытка разгрузить char. Так-то, есть действительно что-то неправильное в том, что строковый тип смешан с числовым. По-хорошему, еще в C имело смысл сделать отдельно тип byte, и отдельно — char.

ЕМ>> А что появилось в языке для замены шаблонной магии?


BFE>auto


Что, прям всей?

BFE>Метапрограммирование ещё только предлагают, но какое-то некрасивое.


Какое метапрограммирование Вы сочли бы красивым?
Re[20]: Как записать такое в современном C++?
От: so5team https://stiffstream.com
Дата: 01.08.24 05:00
Оценка:
Здравствуйте, kov_serg, Вы писали:

S>>А речь точно идет о C++?


S>>https://wandbox.org/permlink/RWneePV7jikXCdQy


_>А теперь представьте что константы надо объявить в header-е


Пару десятков лет так делаю и полет (для примитивных типов) нормальный.

_>
_>extern const int a;
_>


А не надо в C++ тянуть привычки из чистого Си.

_>И всё приплыли.


Отучаемся говорить за всех (c)

До появления constexpr и inline const были проблемы с декларацией в хидерах констант сложных типов, вроде std::string или std::vector. Но это уже совсем другая история.

_>А enum-ы можно объявлять где попало и они constexpr.


До C++11 enum-ы были единственным нормальным способом объявлять константы в метапрограммировании, т.к. в C++98 можно было так:
template<class T>
struct some_metafunc {
  enum { value = 1 };
};

но нельзя было вот так:
template<class T>
struct some_metafunc {
  static const bool value = true;
};
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.