Здравствуйте, netch80, Вы писали:
N>Совместимость.
Сломана нахрен.
N>Изобретать методы как впихнуть туда что-то новое
А что именно новое туда надо впихнуть?
N>во-первых, делает всё с нуля
Не ну типичный NIH
N> во-вторых, использует рефлексию (или compile-time аналог)
C++ может это делать и с %
N>Поэтому там концентрация на том, _как_ форматировать, а не том, _что_ форматировать из входного потока байтов или регистров.
Я уже несколько раз пальцем показал как это сделать на С++ с %
И это у меня работало ещё до появления C++0x
CC>>Ну и к тому же типичный NIH N>Уже давно нет.
Всё ещё да, если мы говорим про С++
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
N>>Совместимость. CC>Сломана нахрен.
Из printf в printf? То есть раньше %s, %d и так далее в printf — значили одно, а сейчас другое? Пример в студию, или считаю, что соврал.
N>>Поэтому там концентрация на том, _как_ форматировать, а не том, _что_ форматировать из входного потока байтов или регистров. CC>Я уже несколько раз пальцем показал как это сделать на С++ с % CC>И это у меня работало ещё до появления C++0x
У тебя был разборщик форматной строки в compile-time до C++0x? На чистом C++98?
Здравствуйте, netch80, Вы писали:
N>У тебя был разборщик форматной строки в compile-time до C++0x? На чистом C++98?
mpl не в C++0x появился, так что принципиальных ограничений (кроме как на фиксированый лимит аргументов) не было
другое дело что вряд-ли кто-то этим для принта заморачивался
Здравствуйте, netch80, Вы писали:
N>У тебя был разборщик форматной строки в compile-time
У меня был type safe/agnostic printf где то в 2008м.
Тот самый в котором можно было на любой тип писать %s и оно правильно работало.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
S>>Если мы этот самый спецификатор шлем вдоль CC>А зачем? Всё равно надо терминатор, так что ничего не трогаем, оставляем как есть, меняется только смысл спецификаторов, которые теперь означают не тип передаваемого параметра а желаемое преставление параметра. Т.е. "s" банально становится as string, что одновременно становится аналогом "{}" CC>Что и обеспечивает обратную совместимость и не приводит к парадоксам типа "%%".
А совместимость с printf многим нафиг не упала еще в 1990-х, потому что printf поддерживал вывод содержимого пользовательских типов практически никак.
Ну и иметь print, который по %i будет автоматом отображать float не поперхнувшись, ну такое себе. Я бы не хотел.
Как и объяснять в XXI веке почему используется синтаксис вида %02xs тем, что когда-то, когда меня еще не было на свете, дедушка Керниган с дедушкой Ричи придумали язык Си, в котором был printf, в котором был специальный синтаксис со спецификаторами типов, потом, спустя почти пять десятилетий, оставили всего один спецификатор типа s, который сейчас означает любой тип... В общем, ширина дорожной колеи все еще определяется размерами задниц лошадей в Древнем Риме.
S>>Суть в парности символов открытия и закрытия спецификации формата вывода. CC>А нафига?
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, netch80, Вы писали:
N>>У тебя был разборщик форматной строки в compile-time CC>У меня был type safe/agnostic printf где то в 2008м. CC>Тот самый в котором можно было на любой тип писать %s и оно правильно работало.
Это ответ программиста — ясный, точный и абсолютно бесполезный.
Ты ничего не сказал ни про какие расширения C++ в промежутке от 98 до 11 на это работали (а у большинства компиляторов были какие-то из них), ни какой общий принцип использовался (например, как разбирал форматную строку).
Может, у тебя вообще там через препроцессор вызывался конвертер в ostream<<something
Здравствуйте, netch80, Вы писали:
N>Ты ничего не сказал ни про какие расширения C++ в промежутке от 98 до 11 на это работали (а у большинства компиляторов были какие-то из них), ни какой общий принцип использовался
Я это уже несколько раз говорил, как то надоело повторяться. Супер секретное расширение под названием оператор запятая + __VA_ARGS__ чтоб использование было такое же визуально как и printf, т.е. функция с переменным колвом аргументов
N> например, как разбирал форматную строку.
Этож вообще банальщина. Особенно когда не надо больше поддерживать всякое старьё для указания размерности, типа h или l, потому как тип переданного значения известен на момент компиляции и левой памяти из стека уже не зачерпнуть.
N>Может, у тебя вообще там через препроцессор вызывался конвертер в ostream<<something
Это не получится ибо совместить с форматной строкой будет ну уж очень гемор, но принцип был похожий: класс форматтера, в который кормятся параметры через оператор запятая.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, so5team, Вы писали:
S>А совместимость с printf многим нафиг не упала еще в 1990-х, потому что printf поддерживал вывод содержимого пользовательских типов практически никак.
Вот чего мне никогда не надо было с прошлого века это как раз поддержка вывода пользовательских типов. Всё специфическое выводилось через %s и аналог toString ()
Нафига тащить это именно в форматтер — мне лично не понятно.
S>Ну и иметь print, который по %i будет автоматом отображать float не поперхнувшись, ну такое себе. Я бы не хотел.
А я по результатам многолетнего опыта не хочу чтоб вместо хоть какого то полезного сообщения в логе окажется тупо ничего.
Логгинг не имеет права поперхнуться. Потому форматтер обязан работать по принципу best effort.
S>Как и объяснять в XXI веке почему используется синтаксис вида %02xs
И какой же синтаксис для такого же вывода будет у {} нотации?
S>>>Суть в парности символов открытия и закрытия спецификации формата вывода. CC>>А нафига? S>Проще.
Кому? И чем?
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
S>>Если мы этот самый спецификатор шлем вдоль CC>А зачем? Всё равно надо терминатор, так что ничего не трогаем, оставляем как есть, меняется только смысл спецификаторов, которые теперь означают не тип передаваемого параметра а желаемое преставление параметра. Т.е. "s" банально становится as string, что одновременно становится аналогом "{}" CC>Что и обеспечивает обратную совместимость и не приводит к парадоксам типа "%%".
Не обеспечивает оно обратную совместимость, потому что тип не задаёт однозначно правила печати. Для целых любой знаковости есть x. Для плавучих есть e, f, g, a.
Если ты будешь хотеть, например, %30.10es вместо %30.10e, ты уже сломал совместимость.
Если ты введёшь для этого другие знаки — то тем более.
S>>Суть в парности символов открытия и закрытия спецификации формата вывода. CC>А нафига?
Проще и человеку, и машине, по одинаковой причине: универсальный гарантированный терминатор. С классическим printf ты должен держать в голове (и в таблицах разбора) какие символы финальные, какие — нет. Почему h, j, l, l, L, q, t, z, Z — нефинальные, а a, c, d, e, f, g, i... — финальные? Где логика, кроме того что всё запоминать?
Ну а раз есть потребность в таком терминаторе, то сделать его какой-то из закрывающих скобок велел сам Отец Тьюринг.
Здравствуйте, CreatorCray, Вы писали:
N>>Ты ничего не сказал ни про какие расширения C++ в промежутке от 98 до 11 на это работали (а у большинства компиляторов были какие-то из них), ни какой общий принцип использовался CC>Я это уже несколько раз говорил, как то надоело повторяться. Супер секретное расширение под названием оператор запятая + __VA_ARGS__ чтоб использование было такое же визуально как и printf, т.е. функция с переменным колвом аргументов
__VA_ARGS__ нет в стандарте. Значит, расширения.
N>>Может, у тебя вообще там через препроцессор вызывался конвертер в ostream<<something CC>Это не получится ибо совместить с форматной строкой будет ну уж очень гемор,
Здравствуйте, CreatorCray, Вы писали:
S>>А совместимость с printf многим нафиг не упала еще в 1990-х, потому что printf поддерживал вывод содержимого пользовательских типов практически никак. CC>Вот чего мне никогда не надо было с прошлого века это как раз поддержка вывода пользовательских типов.
А вот мне (и не только мне) надо было.
CC>Всё специфическое выводилось через %s и аналог toString ()
Так это же так себе решение, ведь нужно промежуточную строку сформировать. ИМХО, лучше уж бы toStream.
CC>Нафига тащить это именно в форматтер — мне лично не понятно.
Хотя бы для того, чтобы можно было подхватить спецификаторы вывода. Например, если у меня есть std::vector<unsigned int>, то поменяв буковку в спецификаторе я могу отобразить его содержимое как в десятичном, так в шестандатиричном или даже двоичном представлении.
S>>Ну и иметь print, который по %i будет автоматом отображать float не поперхнувшись, ну такое себе. Я бы не хотел. CC>А я по результатам многолетнего опыта не хочу чтоб вместо хоть какого то полезного сообщения в логе окажется тупо ничего.
А я бы предпочел получить исключение в run-time, если вместо int-а оказывается float, т.к. отображая float как int мы теряем часть информации даже не зная об этом.
CC>Логгинг не имеет права поперхнуться. Потому форматтер обязан работать по принципу best effort.
Ага, и вместо значений 1.025, 1.150, 1.300, 1.400 мы будем видеть 1, 1, 1, 1. При этом, если у нас это дельта по времени между двумя событиями в секундах, то потеря информации о 25ms, 150ms, 300ms, 400ms -- это проблема. Иногда просто афигеть какая проблема.
S>>Как и объяснять в XXI веке почему используется синтаксис вида %02xs CC>И какой же синтаксис для такого же вывода будет у {} нотации?
{:02x}
Причем двоеточие здесь нужно потому, что fmtlib позволяет нумеровать аргументы, т.е. можно делать так: fmt::format("{1:03}: value obtained={0:02x}", value, iteration)
Подробнее можно посмотреть здесь: https://hackingcpp.com/cpp/libs/fmt.html#hfold2a
S>>>>Суть в парности символов открытия и закрытия спецификации формата вывода. CC>>>А нафига? S>>Проще. CC>Кому? И чем?
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, CreatorCray, Вы писали:
N>>>Ты ничего не сказал ни про какие расширения C++ в промежутке от 98 до 11 на это работали (а у большинства компиляторов были какие-то из них), ни какой общий принцип использовался CC>>Я это уже несколько раз говорил, как то надоело повторяться. Супер секретное расширение под названием оператор запятая + __VA_ARGS__ чтоб использование было такое же визуально как и printf, т.е. функция с переменным колвом аргументов
N>__VA_ARGS__ нет в стандарте. Значит, расширения.
В стандарте C99 уже давно.
Стандартизировали и для C++ немного позже.
Здравствуйте, so5team, Вы писали:
CC>>Всё специфическое выводилось через %s и аналог toString () S>Так это же так себе решение, ведь нужно промежуточную строку сформировать. ИМХО, лучше уж бы toStream.
Ну учитывая что за 30 лет комитеты не смогли стандартизовать fopencookie() или funopen() — какой уж там toStream?
CC>>Нафига тащить это именно в форматтер — мне лично не понятно. S>Хотя бы для того, чтобы можно было подхватить спецификаторы вывода. Например, если у меня есть std::vector<unsigned int>, то поменяв буковку в спецификаторе я могу отобразить его содержимое как в десятичном, так в шестандатиричном или даже двоичном представлении.
+100.
S>>>Ну и иметь print, который по %i будет автоматом отображать float не поперхнувшись, ну такое себе. Я бы не хотел. CC>>А я по результатам многолетнего опыта не хочу чтоб вместо хоть какого то полезного сообщения в логе окажется тупо ничего. S>А я бы предпочел получить исключение в run-time, если вместо int-а оказывается float, т.к. отображая float как int мы теряем часть информации даже не зная об этом.
Вот тут сомнительно, что именно исключение. Может быть, лучше предупреждение в логе специальной меткой рядом со значением.
CC>>Логгинг не имеет права поперхнуться. Потому форматтер обязан работать по принципу best effort. S>Ага, и вместо значений 1.025, 1.150, 1.300, 1.400 мы будем видеть 1, 1, 1, 1. При этом, если у нас это дельта по времени между двумя событиями в секундах, то потеря информации о 25ms, 150ms, 300ms, 400ms -- это проблема. Иногда просто афигеть какая проблема.
Ну то что оно напишет 1 вместо 1.0 даже при точной единице — уже может быть подсказкой.
Здравствуйте, netch80, Вы писали:
CC>>>Всё специфическое выводилось через %s и аналог toString () S>>Так это же так себе решение, ведь нужно промежуточную строку сформировать. ИМХО, лучше уж бы toStream.
N>Ну учитывая что за 30 лет комитеты не смогли стандартизовать fopencookie() или funopen() — какой уж там toStream?
По большому счету, если кто-то пишет свой лисапед в обход стандартных iostreams, то он может потребовать наличие у типа метода toStream с некоторой сигнатурой. И параметром в этот toStream может идти не стандартный std::ostream, а какой-то другой тип.
В принципе, наличие этого toStream может проверяться в compile-time разными SFINAE-подобными трюками.
По большому счету, в fmtlib как раз пошли по этому пути, но еще более сурово: там теперь нужно специализацию fmt::formatter делать для своего типа. Что, временами, не сказать, что тривиально (если хочется сделать эффективно, а не через промежуточную строку). И, полагаю, авторы fmtlib пошли так не от хорошей жизни, а потому что проще (но эффективно при этом всем) сделать пока не получилось.
S>>А я бы предпочел получить исключение в run-time, если вместо int-а оказывается float, т.к. отображая float как int мы теряем часть информации даже не зная об этом.
N>Вот тут сомнительно, что именно исключение. Может быть, лучше предупреждение в логе специальной меткой рядом со значением.
Я со своей колокольни смотрю и свое мнение высказываю. Как по мне, так исключение надежнее всего (хотя исключения в проекте вообще могут быть под запретом).
Так-то понятно, что могут быть разные требования и разные взгляды. Но здесь же каждый свое ИМХО излагает. Благодаря чему можно оценить насколько все разнообразно.
Здравствуйте, CreatorCray, Вы писали:
BFE>>Ну вот я писал на системных примитивах и понял, что производительность труда при этом падает на порядок CC>Куда больше интересует производительность результата.
Результат должен укладываться в норму, не более.
BFE>> при переходе на новый процессор CC>Шта?
Ага.
BFE>> или платформу CC>И как часто это происходит в реальности?
От конторы зависит. В одной из контор это было регулярно, каждый год новая плата с абсолютно другой сборкой, процессором и входами/выходами...
BFE>>всё время уходит на копирование структур и массивов. CC>А зачем их всё время копировать?
Потому, что "электронщики" не умеют иначе. Хотите кому-то послать данные? Ну-давайте-мы-их-скопируем-в-свой-буфер и будем медленно, битик за битиком посылать... Обменяться указателями на буфер? Это вы чего тут выдумали? Мы так не умеем... Вот наш буфер, мы им дорожим и никому не отдаём. Все данные только через него.
Здравствуйте, so5team, Вы писали:
S>А вот мне (и не только мне) надо было.
С++ хорош тем, что ты можешь пользоваться тем, что надо тебе.
А не заставлять всех остальных пользоваться тем, что им не нужно.
S>А я бы предпочел получить исключение в run-time
Когда в критичной ветке вместо лога происходит исключение и всё просирается — я за такое давно уже готов лично расстреливать.
S>Ага, и вместо значений 1.025, 1.150, 1.300, 1.400 мы будем видеть 1, 1, 1, 1. При этом, если у нас это дельта по времени между двумя событиями в секундах, то потеря информации о 25ms, 150ms, 300ms, 400ms -- это проблема. Иногда просто афигеть какая проблема.
Это всяко лучше когда не вывелось вообще ничего.
S>{:02x}
И чем это лучше чем
%02x
?
S>проще запоминать.
Вот это ты щас серьёзно?
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
S>>А вот мне (и не только мне) надо было. CC>С++ хорош тем, что ты можешь пользоваться тем, что надо тебе. CC>А не заставлять всех остальных пользоваться тем, что им не нужно.
Продолжая логическую цепочку: если мне printf не нужен был в течении многих и многих лет, то зачем мне держаться за его синтаксис?
S>>А я бы предпочел получить исключение в run-time CC>Когда в критичной ветке вместо лога происходит исключение и всё просирается — я за такое давно уже готов лично расстреливать.
Если критичная ветка не была протестирована и никто не знал, что там вместо одного типа подсовывается другой -- вот это серьезно. Но расстреливать вы собираетесь гонца, который принес вам дурную весть. Ну, OK.
S>>Ага, и вместо значений 1.025, 1.150, 1.300, 1.400 мы будем видеть 1, 1, 1, 1. При этом, если у нас это дельта по времени между двумя событиями в секундах, то потеря информации о 25ms, 150ms, 300ms, 400ms -- это проблема. Иногда просто афигеть какая проблема. CC>Это всяко лучше когда не вывелось вообще ничего.
Ничего подобного. Если события должны выполняться в течении 20 тактов, а в логе получается, что они выполнились всего за один такт, то прежде чем выяснить проблемы с логированием будет потрачено время на попытки выяснить как же так получилось, что все произошло в одном такте. А в итоге получится, что лог можно пустить в утиль, т.к. актуальной привязки ко времени там нет. И это далеко "не всяко лучше".
S>>{:02x} CC>И чем это лучше чем
%02x
?
Позволю себе процитировать ув.тов.netch80, который уже все хорошо расписал:
Проще и человеку, и машине, по одинаковой причине: универсальный гарантированный терминатор. С классическим printf ты должен держать в голове (и в таблицах разбора) какие символы финальные, какие — нет. Почему h, j, l, l, L, q, t, z, Z — нефинальные, а a, c, d, e, f, g, i... — финальные? Где логика, кроме того что всё запоминать?
S>>проще запоминать. CC>Вот это ты щас серьёзно?
Да, запомнить, что для дефолта нужно написать просто {} вместо правил выбора между %s, %i, %f и пр., легче.
Здравствуйте, so5team, Вы писали:
S>Продолжая логическую цепочку...
Не знаю как тебе а мне эта сказка про белого бычка уже надоела...
S>Если критичная ветка не была протестирована
Очень далеко не всё и не всегда можно протестировать.
S>Но расстреливать вы собираетесь гонца, который принес вам дурную весть. Ну, OK.
Не, я как раз хочу чтоб никого не расстреляли и гонец хоть что то промямлил.
S>Позволю себе процитировать ув.тов.netch80, который уже все хорошо расписал:
Он за деревьями не увидел леса.
После того, как тебе не надо задавать передаваемые размерности всякие "нефинальные" попросту отмирают.
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, so5team, Вы писали:
S>>>А я бы предпочел получить исключение в run-time, если вместо int-а оказывается float, т.к. отображая float как int мы теряем часть информации даже не зная об этом. N>>Вот тут сомнительно, что именно исключение. Может быть, лучше предупреждение в логе специальной меткой рядом со значением. S>Я со своей колокольни смотрю и свое мнение высказываю. Как по мне, так исключение надежнее всего (хотя исключения в проекте вообще могут быть под запретом).
Так исключения для целевого кода — могут как раз быть осмысленными, если ему лучше остановиться, чем сделать плохое — но тут точно вопрос контекста и даже вкуса.
А вот выбить логгирование — имеет смысл только тогда, когда это портит сам лог (ну типа скинуть бинарный блоб в текстовую форму, или гигабайт мусора), тут я не вижу, чем можно вообще возражать.
S>Так-то понятно, что могут быть разные требования и разные взгляды. Но здесь же каждый свое ИМХО излагает. Благодаря чему можно оценить насколько все разнообразно.
Ну вот я и не могу понять из каких соображений может быть лучше не логгировать — или даже вышибать работу целевого кода из-за проблем отладочно-диагностического логгирования.