LINUX.ORG.RU

Производительность C++

 ,


7

13

Как насчёт производительности у C++ по сравнению с C? Мои предположения на текущий момент:

1) Код, не использующий возможности C++ (то есть по сути plain C), скомпилированный C++ компилятором будет иметь абсолютно ту же производительность, что и код на С.

2) Исключения и dynamic_cast медленные. Если нам важна производительность, лучше их не использовать.

3) Класс без виртуальных методов, должен быть по производительности эквивалентен сишной структуре и функциям, обрабатывающим её. Не считая копирования. Нужно везде, где можно использовать передачу по указателю или ссылке (собственно, если в Си делать memmove при передаче структуры в качестве аргумента, то это вызовет примерно такой же оверхед, как дефолтный конструктор копирования С++. Верно?).

4) Класс с виртуальными методами полностью аналогичен пункту 3, но при вызове виртуальных методов добавляется небольшой оверхед. Сишный эквивалент obj->vtable->func(obj, ...). Если сравнивать с plain C кодом, реализующим ООП в той же манере (каждая структура-объект имеет поле, указывающее на структуру, содержащую адреса функций работы с ней), то оверхеда по сравнению с plain C не должно быть.

5) При использовании атрибута класса final (если компилятор поддерживает соответствующий стандарт) даже при наличии виртуальных методов в нём, их вызов будет превращаться в прямые вызовы функций вместо обращения к vtable, если переменная имеет соответствующий тип, а не указатель/ссылка на его предка (который не final).

6) Шаблоны могут привести к разбуханию кода. Впрочем, #define-ы и inline-функции в C++ могут устроить то же самое. Вопрос: будет ли использование шаблона с одинаковыми параметрами создавать 2 копии реализации или же всё-таки компилятор догадается сделать её лишь один раз. А если шаблон используется с одинаковыми параметрами в нескольких объектных файлах? Будет ли реализация расшариваться между ними или у каждого своя?

7) Что насчёт inline-методов класса? (те, которые описываются прямо в момент определения самого класса, внутри блока class). Может ли их реализация расшариваться между модулями или в каждом будет своя копия (допустим, метод слишком длинный, чтобы инлайнится в момент вызова)?

Я не претендую на правоту, какие-то утверждения могут быть ложными. Хотел бы узнать, как обстоят дела на самом деле. А также какие подводные камни я ещё не знаю. Разумеется, речь идёт о последних версиях gcc/clang с включённой оптимизацией не ниже -O2.

★★★★★

Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от anonymous

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

По фактам того, что я здесь говорил претензии есть?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Чот вы тут сильно дофига уже с этим анонимным смайликом трете. не надоело кормить?

Кста по возврату. У нас был Result<T, E> в качестве результата функций API задолго до того, как появился раст.

anonymous
()
Ответ на: комментарий от anonymous

У нас был Result<T, E> в качестве результата функций API задолго до того, как появился раст.

Кто в данном случае «мы» - Haskell, Scala?

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Чот вы тут сильно дофига уже с этим анонимным смайликом трете. не надоело кормить?

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

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Кста по возврату. У нас был Result<T, E> в качестве результата функций API задолго до того, как появился раст.

По накладным расходам Result<int, string>, который можно было бы применить в библиотеке вроде picojson, будет ничуть не лучше возврата просто string-а.

Так что возврат просто string плох прежде всего тем, что нет возможности классифицировать ошибку (например, отличить отсутствие закрывающей фигурной скобки от неверного формата записи целого числа). Но во многих сценариях использования json-а это и не нужно: либо json парсится успешно, либо нет. И если нет, достаточно залогировать текстовое описание.

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

eao197 ★★★★★
()
Ответ на: комментарий от tailgunner

Да особо не напрягало. там строго все было. E - наследники от определенного класса (EBase; проверялось при компиляции), если собиралось с исключениями, то EBase был наследником от exception и мог быть кинут. Сам Result имел оператор bool и легко проверялся if( r ) { ... }.

anonymous
()
Ответ на: комментарий от anonymous

а аноним не из ебурга ? стиль мышление похож на одного кадра

anonymous
()
Ответ на: комментарий от anonymous

E - наследники от определенного класса (EBase; проверялось при компиляции)

Экземпляр передавался через указатель?

tailgunner ★★★★★
()
Ответ на: комментарий от eao197

По фактам того

Да ты как-то фактов-то особо никаких не привел. Все, что я увидел, прочитав тред, это ``дебил, школьник, лень объяснять, никто не пользуется си, вы все тупые, разрабатывать на плюсах дешевле, я сказал!".

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

anonymous
()
Ответ на: комментарий от eao197

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

Ну какие бредни смайлик высказал? :-) Он всего лишь намекает, что язык должен использоваться либо полностью, либо никак :-) Если исключения портят малину, нужно отказываться от C++ в пользу того же C, а не кушать кактусы :-) Просто же всё у нас с этим :-)

anonymous
()
Ответ на: комментарий от tailgunner

Ошибки - да.

А результат трейтами определялся. Через указатели (большие матрицы например) или прям в теле (если там один float).

anonymous
()
Ответ на: комментарий от anonymous

Ну какие бредни смайлик высказал? :-)

Ну вот например:

улыбчивый_дурачок> язык должен использоваться либо полностью, либо никак

улыбчивый_дурачок> Если исключения портят малину, нужно отказываться от C++ в пользу того же C,

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от anonymous

Все, что я увидел, прочитав тред, это ``дебил, школьник, лень объяснять, никто не пользуется си, вы все тупые, разрабатывать на плюсах дешевле, я сказал!".

А теперь попробуйте ответить за свои слова и показать, где я говорил, например, про «никто не пользуется си».

Ну и как можно назвать человека, который не видит в стандарте явного указания того, что спецификатор throw deprecated да еще и кичится этим?

eao197 ★★★★★
()
Ответ на: комментарий от tailgunner

Ты лишь цитируешь некоего смайлика :-) Зачем лишний раз гонять трафик, если его высказывания итак все увидели :-) Почему ты никогда не обосновываешь свои заявления, как и в этом случае, ограничиваясь лишь бессмысленным цитированием? :-)

anonymous
()
Ответ на: комментарий от anonymous

Зачем лишний раз гонять трафик, если его высказывания итак все увидели

Ты задал вопрос - я на него ответил.

Почему ты никогда не обосновываешь свои заявления

Когда я говорю с разумным человеком - обосновываю. Но ты не являешься разумным человеком.

tailgunner ★★★★★
()
Ответ на: комментарий от eao197

Ну и как можно назвать человека, который не видит в стандарте явного указания того, что спецификатор throw deprecated да еще и кичится этим?

Ну так возникает вопрос, что, неужто человека, не увидевшего в 1300 страничном стандарте строчку про deprecated, называть дебилом может лишь абсолютный чемпион по C++? :-)

anonymous
()
Ответ на: комментарий от tailgunner

Когда я говорю с разумным человеком - обосновываю. Но ты не являешься разумным человеком.

Являюсь, ведь моему разуму не ведомо возвращать ошибку в виде std::string и функции синтаксического разбора, в отличии от :-)

anonymous
()
Ответ на: комментарий от eao197

throw deprecated

Это че, теперь исключения нельзя выбрасывать? Интересно, и какой ныне идиоматический способ сообщения об ошибке в крестах? А потом он говорит, что никто с крестами не знаком. Авторы бы хоть определились с каким-то образом языка, что есть кресты, как не прикрученный к сишке набор разрозненных фич, еще и объявляющихся устаревшими.

anonymous
()
Ответ на: комментарий от anonymous

Это че, теперь исключения нельзя выбрасывать? Интересно, и какой ныне идиоматический способ сообщения об ошибке в крестах? А потом он говорит, что никто с крестами не знаком.

И ещё удивительно, насколько я помню, eao197 много раз нахваливал механизм исключений в цепепе, что в случае вложенности вызовов это способ сообщить об ошибке вниз по стеку... :-) Но тут потребовалось обосновать рекомендацию tailgunner по использованию библиотеки, в которой вместо значения результата парсинга вдруг возвращается std::string с ошибкой :-) Вот ведь аномалия :-)

anonymous
()
Ответ на: комментарий от anonymous

И пошла заливка про «ключи компилятора» и про поставленные в жёсткие рамки команды программистов на C++, которые вынуждены отказываться от большой части языка, который они же и применяют :-) Ну где логика, мне не понятно, например :-)

anonymous
()
Ответ на: комментарий от anonymous

Это че, теперь исключения нельзя выбрасывать?

Можно. Просто практика показала, что спецификатор throw оказался плохой идеей. Подробнее здесь: http://www.gotw.ca/publications/mill22.htm

Теперь, чтобы показать, что функция/метод не бросает исключение, используется спецификатор noexcept. Если спецификатора нет, то функция/метод может бросить все, что угодно.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Это не ответ на мой вопрос.

Еще раз, может с третьего раза дойдет:

какой ныне идиоматичный способ сообщения об ошибке в крестах?

anonymous
()
Ответ на: комментарий от anonymous

Речь про спецификатор, тот что в сигнатуре, а не оператор.

mix_mix ★★★★★
()
Ответ на: комментарий от eao197

Если спецификатора нет, то функция/метод может бросить все, что угодно.

Более того, как выясняется, она и вернуть может всё, что угодно :-) И для этого достаточно лишь одного типа данных - std::string :-) Лол :-)

anonymous
()
Ответ на: комментарий от anonymous

какой ныне идиоматичный способ сообщения об ошибке в крестах?

Нет такого. В проектах, где использование исключений разрешено, используют исключения. В проектах, где исключения запрещены, применяются разные подходы (будь то errno/SetLastError/GetLastError, или же коды возврата).

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Нет такого.

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

anonymous
()
Ответ на: комментарий от anonymous

Так и надо было говорить сразу.

Позволю себе напомнить столь внимательному читателю, что речь шла о спецификаторе throw. А вовсе не об отмене исключений, как вам могло показаться.

Херово это крайне.

Ну уж как есть.

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

С-шные либы тоже бывают разные. В некоторых возвращается 0 как индикатор успеха, а все остальные значения — это коды ошибок. В некоторых возвращается -1 как признак неудачи, а код ошибки нужно смотреть в errno.

Так что без чтения документации и в C не обойтись.

И потом кто-то тут говорит про дешевую разработку на плюсах, когда разные либы даже сообщения об ошибках по-разному возвращают.

И вновь позволю себе указать столь внимательному читателю, что речь шла про более дешевую разработку на C++ по сравнению с C.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Нет такого. В проектах, где использование исключений разрешено, используют исключения. В проектах, где исключения запрещены, применяются разные подходы (будь то errno/SetLastError/GetLastError, или же коды возврата).

Ложь и подмена понятий :-) Тебя же спросили про идиоматичный способ, а не про существование проектов, в которых тужатся изо всех сил, чтобы избегать идиоматичных способов по каким-либо причинам :-) А еще в CppCoreGuidelines сказано следующее: «If you can't use exceptions (e.g. because your code is full of old-style raw-pointer use or because there are hard-real-time constraints), consider using a style that returns a pair of values» :-) Так что не надо сочинять :-)

anonymous
()
Ответ на: комментарий от anonymous

И ещё удивительно, насколько я помню, eao197 много раз нахваливал механизм исключений в цепепе, что в случае вложенности вызовов это способ сообщить об ошибке вниз по стеку... :-) Но тут потребовалось обосновать рекомендацию tailgunner по использованию библиотеки, в которой вместо значения результата парсинга вдруг возвращается std::string с ошибкой :-) Вот ведь аномалия :-)

Если это и аномалия, то только вашего восприятия действительности. Я всегда говорил, что исключения лучше, чем коды возврата. Но есть условия, когда исключения применять нельзя. И тогда уже ничего другого не остается.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Но есть условия, когда исключения применять нельзя. И тогда уже ничего другого не остается.

Опять ложь :-) В таких случаях разумнее использовать просто C :-)

anonymous
()
Ответ на: комментарий от eao197

Да что там далеко ходить, в том же ведре в одном месте код 0 значит нет ошибки, в соседней функции — есть.

mix_mix ★★★★★
()
Ответ на: комментарий от anonymous

мне просто интересно, откуда у плюсовиков такой фанатизм и неприязнь к другим языкам.

Ну вот не надо, в твоих словах тоже предвзятость чувствуется. Собственно, даже в этой теме «фанатизм и неприязнь» «с другой стороны» тоже демонстрируют.

Возможно, плюсы и правда привлекают больше «фанатиков», которые думаю, что это «мощный и быстрый язык», но это совсем не уникально. Хватает и упёртых сишников уверенных, что ничего другого просто не нужно и лисперов восторгающимися теоретической «невероятной гибкостью» языка. А уж повёрнутого жабаскриптера я думаю ты и сам на этом форуме встречал.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Он всего лишь намекает, что язык должен использоваться либо полностью, либо никак :-)

Но ведь это ерунда. Даже в С, при всей его простоте, не всегда прямо уж всё задействуется. И наоборот - если надо, то используются расширения языка. В CL не всегда используют, скажем, CLOS. В хаскеле целая куча вещей является «полустандартными» и прячется за ключами, но при этом нередко используется. С++ тут ничем не отличается и при отказе от отдельных частей всё равно могут быть полезны остальные.

А вообще это смешно, учитывая как ты в других темах доказывал о том, что от исключений «все отказались» и размахивал тем же Qt.

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

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

повёрнутого жабаскриптераповёрнутого жабаскриптера

Так даже тот уважает как минимум смоллток, еще какие-то там ТРУООПЯЗЫКИ!!! Лисперы ближе, да. Сишников упоротых не встречал, ибо те обычно как минимум на пистоне и го пишут тоже. Да и кресты — единственный язык, который пытался пролезть всюду в свое время, от веба до ядер, и который автор до сих пор позиционирует как серебряную пулю (да, как и грэхэм позиционирует борщелисп аки панацею).

anonymous
()
Ответ на: комментарий от anonymous

Да и кресты — единственный язык, который пытался пролезть всюду в свое время, от веба до ядер

Саночники это пытались и с Java сделать. А мелкомягкие и с C#.

Да и вам бы с Oberon-щиками бы пообщаться. Вот там вааще жесть.

Ну и непонятно, если в теме про производительность C++ относительно C не защищать C++, то где тогда это следует делать? ;)

eao197 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Даже в С, при всей его простоте, не всегда прямо уж всё задействуется.

Ты пытаешься подменить понятия, но у тебя ничего не выйдет :-) Речь не о том, чтобы каждый «Здравствуй, мир!» писать используя все возможности языка, а речь о том, что в цепепе для сигнализации об ошибках специально придумали механизм исключений :-) Потом написали тонны книг о том, как нужно программировать на цепепе :-) И тут выясняется, что без этого всего можно обойтись :-) Достаточно лишь взять какой-нибудь picojson со строкой с ошибкой вместо результата парсинга и воспользоваться каким-нибудь -fno-exceptions :-) Ну а что, цепепе - он такой :-)

В CL не всегда используют, скажем, CLOS.

Опять ты пытаешься замылить дискуссию о неидиомотичности :-) В CL никому и в голову не придёт отказываться от сигнального протокола в пользу возврата ошибки в виде строки :-) Такая пурга любому лисперу лишний раз продемонстрирует печальную для цепепе ситуацию :-)

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

Одно дело отказываться от «отдельных частей», а другое дело говнокодить в стиле «а не вернуть лишь мне ошибку в строке» :-)

А вообще это смешно, учитывая как ты в других темах доказывал о том, что от исключений «все отказались» и размахивал тем же Qt.

Ну, то, что исключения в цепепе на фоне сигнального протокола в Лиспе - это серая серость и я сейчас могу доказать легко :-) Что же касается в Qt, то там ошибки в std::string таки не заворачиваются, несмотря на то, что исключений нет :-) Ты ж пойми, std::string - это есть строка, а std::runtime_error - это ошибка :-) Лол :-)

anonymous
()
Ответ на: комментарий от anonymous

Так даже тот уважает как минимум смоллток, еще какие-то там ТРУООПЯЗЫКИ!!!

Дык, в том и дело. Он отказывается понимать, скажем, полезность макросов в лиспе из-за того, что они «работают не в рантайме» или то, что иногда вполне стоит пожертвовать «тру ооп-шностью» ради производительности. Что это как не упёртый фанатизм? То, что он устремлён на «идею», а не конкретный язык сильно дело не меняет. Причём есть подозрения, что если бы его любимый Io был хоть немного популярнее, то на джаваскрипт и смоллток он меньше ссылался бы.

Сишников упоротых не встречал

Eddy_em?..

единственный язык, который пытался пролезть всюду в свое время

Ну а сейчас «время джаваскрипта». Тоже всюду лезет «потому что может».

и который автор до сих пор позиционирует как серебряную пулю

Мы об «автор языка»? Было бы странно, если бы он евангелизмом не занимался, но мне казалось, что он далёк от фанатизма и призывов писать всё на плюсах. Впрочем, последнее его творчество не читал.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Нет, ты. Про строку я ничего не говорил.

Конечно, ты просто выдрал фразу об отказе от использования исключений из контекста, оправдывающего такой отказ в угоду возврата std::string с текстом ошибки :-) Ну и начал рассказывать про то, что в Лиспе не всегда используется CLOS, а C не всегда используется полностью :-) Меня не проведёшь :-)

anonymous
()
Ответ на: комментарий от anonymous

А если таки нужен «C с классами»? Всё же в C++ и без исключений есть достаточно много полезного сахара. А писать простыни макросов на Си для реализации ООП своими силами - это и есть кушанье кактусов. Ибо вместо 10 строчек получается 100. Производительность труда программиста падает, вероятность появления багов растёт.

Вот, допустим, у тебя есть две сумки. Одна большая, другая маленькая. В маленькую нифига не влезают твои вещи, а большую влезает, но остаётся много свободного пространства. Какую сумку ты выберешь? Любой нормальный человек выберет большую сумку, а не будет тащить часть вещей в руках (именно это ты и предлагаешь). Язык должен уметь не меньше, чем нужно программисту. Если же он умеет больше, ничто не мешает не использовать ненужную часть.

Да, оптимальный вариант - взять сумку нужного размера. Но покажи мне язык программирования без исключений, но с классами и производительностью C++.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Потому что в типичном use-case этой либы программе нафиг не нужно знать больше информации об ошибке. Ей тупо надо показать максимально информативное сообщение ПОЛЬЗОВАТЕЛЮ.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от KivApple

Потому что в типичном use-case этой либы программе нафиг не нужно знать больше информации об ошибке. Ей тупо надо показать максимально информативное сообщение ПОЛЬЗОВАТЕЛЮ.

В таком случае следовало бы просто использовать тип std::runtime_error, в который и передать информацию, которая подлежит для вывода ПОЛЬЗОВАТЕЛЮ через what() :-) Тогда намерения автора были бы понятны :-) А так, пользуйся, если нравится, выдавай ПОЛЬЗОВАТЕЛЮ сообщения об ошибке, отключай исключения и т.д., как пожелаешь :-) Всего хорошего :-)

anonymous
()
Ответ на: комментарий от anonymous

В таком случае следовало бы просто использовать тип std::runtime_error, в который и передать информацию, которая подлежит для вывода ПОЛЬЗОВАТЕЛЮ через what()

Код, покажите как будет выглядеть этот код!

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Это же так просто :-) Оставим runtime_error, т.к. конструкторы его не noexcept :-) Хотя, с твоим опытом, ты поймёшь, конечно, как это сделать :-) Итак, специально для тебя,

#include <cassert>
#include <cstdio>
#include <cstring>

class Error {
public:
  Error() noexcept =default;
  Error(const char* msg) noexcept : msg_(msg) {}

  const char* what() const noexcept { return msg_; }

  bool really_error() const noexcept { return std::strcmp(what(), "") != 0; }
private:
  const char* msg_{""};
};

Error error() noexcept
{
  return Error("The error occurred");
}

Error ok() noexcept
{
  return Error();
}

void test_error(const Error& e) noexcept
{
  std::fprintf(stderr, e.really_error() ? "error\n" : "ok\n");
}

int main(int argc, char *argv[])
{
  assert(error().really_error());
  assert(!ok().really_error());

  test_error(error());
  test_error(ok());

  return 0;
}

Теперь можешь отключать исключения, т.к. везде, где надо, noexcept :-) Всего хорошего :-)

anonymous
()
Ответ на: комментарий от anonymous

Оставим runtime_error

Слив. Уже, прям с ходу. А как дышал, как дышал.

т.к. конструкторы его не noexcept

Матчасть таки нужно учить. Малолетним дебилам особенно.

Но смотрим главное:

class Error {
public:
  Error() noexcept =default;
  Error(const char* msg) noexcept : msg_(msg) {}

  const char* what() const noexcept { return msg_; }

  bool really_error() const noexcept { return std::strcmp(what(), "") != 0; }
private:
  const char* msg_{""};
};

Как в это говно передать динамически сформированную строку? А, смайлик? Опять наговнокодил?

Ну и главное: покажи, как это говно на палочке этот волшебный Error смог бы улучшить API picojson?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Слив. Уже, прям с ходу. А как дышал, как дышал.

Хотел ведь как лучше, думал поймёшь, всё таки 20 лет программируешь на C++, но не сложилось :-) Что же, runtime_error, так runtime_error :-)

#include <cassert>
#include <cstdio>
#include <cstring>
#include <stdexcept>

std::runtime_error error()
{
  return std::runtime_error("The error occurred");
}

std::runtime_error ok()
{
  return std::runtime_error("");
}

inline bool really_error(const std::runtime_error& e) noexcept
{
  return std::strcmp(e.what(), "") != 0;
}

void test_error(const std::runtime_error& e) noexcept
{
  std::fprintf(stderr, really_error(e) ? "error\n" : "ok\n");
}

int main(int argc, char *argv[])
{
  assert(really_error(error()));
  assert(!really_error(ok()));

  test_error(error());
  test_error(ok());

  return 0;
}

Матчасть таки нужно учить. Малолетним дебилам особенно.

Да, да, см. в стандарт на сигнатуру конструктора runtime_error :-) Там нет noexcept :-)

Как в это говно передать динамически сформированную строку? А, смайлик? Опять наговнокодил?
Ну и главное: покажи, как это говно на палочке этот волшебный Error смог бы улучшить API picojson?

Не нервничай ты так, экономь силы для своего фреймворка акторов, или что там у тебя :-) Ну, это улучшит API тем, что хотя бы будет видно, что возвращается ошибка :-) Не зря же типы и всё такое имеют место быть :-) Всего хорошего :-)

anonymous
()
Ответ на: комментарий от anonymous

Хотел ведь как лучше

Вы не умеете лучше. Вы даже не умеете так, как говорите.

std::runtime_error ok()
{
  return std::runtime_error("");
}

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

Да, да, см. в стандарт на сигнатуру конструктора runtime_error :-) Там нет noexcept :-)

Дебилушка, вам не в стандарт на сигнатуру методов runtime_error смотреть нужно. А в учебники, которые объясняют, как и для чего используется noexcept.

Не нервничай ты так, экономь силы для своего фреймворка акторов, или что там у тебя :-)

Да я вообще из-под стола пишу. Очередной эпичный фэйл анонима-со-смайликами. И очередное подтверждение того, что C++ громче всего хэйтят те, кто в C++ не могут.

Ну и за меня не беспокойтесь. Сил хватит.

Ну, это улучшит API тем, что хотя бы будет видно, что возвращается ошибка :-)

Т.е. вы предложили из parse всегда возвращать runtime_error, даже когда ошибок нет. А проверять ошибки нужно путем вызова какой-то левой really_error, которая никаким боком с runtime_error не связана? А в случае успешного разбора будет возвращаться runtime_error, созданный вашей говнофункцией ok()? И все это по-вашему лучше, чем есть сейчас в picojson?

Б**, откуда только такие дебилы вылазиют?...

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Итак, рассуждения профессионального C++-программиста:

Вы не умеете лучше.
Вы даже не умеете так, как говорите.
подсчитайте, какие накладные расходы на возврат пустого runtime_error.
Дебилушка, вам не в стандарт на сигнатуру методов runtime_error смотреть нужно.
Да я вообще из-под стола пишу.
Очередной эпичный фэйл анонима-со-смайликами.
очередное подтверждение того, что C++ громче всего хэйтят те, кто в C++ не могут.
Ну и за меня не беспокойтесь. Сил хватит.
really_error(const runtime_error&), которая никаким боком с runtime_error не связана?
Б**, откуда только такие дебилы вылазиют?...

anonymous
()
Ответ на: комментарий от anonymous

Сказать то чего хотели? Или мне нужно вложить вам в голову объяснения по основным пунктам из составленного вами списка?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Сказать то чего хотели?

То, что ты, сидя под столом, не знаешь даже, что такое noexcept, раз никак до тебя не доходит в чём смысл Error parse(..) noexcept :-) Всё про какие-то учебники указывает :-) Эксперт, называется :-)

Или мне нужно вложить вам в голову объяснения по основным пунктам из составленного вами списка?

Не нужно :-)

anonymous
()
Ответ на: комментарий от anonymous

Не нужно :-)

А там я не у вас спрашивал. С вами-то все понятно. Тем более после очередной демонстрации.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

А там я не у вас спрашивал.

Мало того, что ты C++ знаешь так себе, так ещё и не можешь определить с кем общаешься :-) Тот список, составленный из твоей словесной желчи составил смайлик :-)

С вами-то все понятно. Тем более после очередной демонстрации.

Так смайлик свои слова подкрепил корректным, чистым и понятным кодом, а твоя аргументация состояла лишь из мерзких оскорблений и признания, что ты находишься под столом :-)

anonymous
()
Ответ на: комментарий от anonymous

смайлик свои слова подкрепил несложным говнокодом

/fixed

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

Мало того, что ты C++ знаешь так себе, так ещё и не можешь определить с кем общаешься :-)

В упор не видел там ваших фирменных опознавательных знаков.

Так смайлик свои слова подкрепил корректным, чистым и понятным кодом

Бгг. Ща проржусь, пройдусь по вашему коду подробнее.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

а твоя аргументация состояла лишь из мерзких оскорблений

Ну, поехали. Некий дебилоид, обильно расставляющий смайлики в своих текстах, заявил, что следовало бы возвращать из parse объект runtime_error. На просьбу показать код, этот дебилоид показывает вариант, в котором вообще нет runtime_error. Более того, показанный класс Error в принципе не предназначен для работы с динамическими строками (а ведь сообщения об ошибках являются таковыми). Тогда как использование std::string в picojson этой проблемы не имеет по определению.

Далее, в попытке ответить за свои слова дебилоид-со-смайликами показывает вариант с runtime_error, но что из себя этот вариант представляет?

А представляет этот вариант не что иное, как возврат все того же std::string-а все с теми же сценариями использования. Т.е. пустой std::string — нет ошибки, не пустой — есть ошибка.

Только вот сейчас этот std::string завернут в runtime_error (который наследуется от std::exception). Т.е. возврат все того же std::string из parse в варианте дебилоида-со-смайликами будет требовать не только конструирования std::string, но и вызова еще двух конструкторов (std::exception и std::runtime_error).

При этом стоит напомнить про то, что все это происходит в топике, где сравнивается производительность C++ относительно производительности C. А как раз из-за таких дополнительных накладных расходов в реальной жизни C++ный код немного, но проигрывает в скорости коду на C.

Итак, что мы видим в итоге: все тот же возврат строки из parse, но завернутый в никому ненужную обертку ради придури анонимного дебилоида.

И это пока только «по большому сверху» :)

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

а твоя аргументация состояла лишь из мерзких оскорблений

Ну а теперь парочка частностей. Посмотрим на мегаговнофункцию ok():

std::runtime_error ok()
{
  return std::runtime_error("");
}
Что здесь будет происходить в STL-е, в котором для std::string нет small string optimization? А будет вызов new для создания строки, содержащей всего один ноль-символ.

Если уж так хотелось возвратить runtime_error с пустой строкой, то можно было бы написать так: runtime_error(std::string()). Но это же C++ хоть чуть-чуть знать нужно.

Но все это херня по сравнению с тем, что в picojson вообще нет никаких накладных расходов на возврат пустого std::string. Ведь у авторов picojson нет смайликов в мозгах, поэтому им нет необходимости оборачивать std::string в никому не нужный здесь runtime_error.

Ну и совсем чуть-чуть про really_error. В случае с std::string-ом пользователю picojson-а не нужно ничего знать. Достаточно только интерфейса самого std::string. В случае с runtime_error от дурносмайлика пользователь parse должен помнить, что проверить содержимое возвращенного runtime_error нужно с помощью какой-то левой функции really_error, лежащей совсем в другом пространстве имен.

А вот про noexcept ничего вам объяснять не буду — вас учить, только портить :)

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Более того, показанный класс Error в принципе не предназначен для работы с динамическими строками (а ведь сообщения об ошибках являются таковыми)

Ему и не надо в данном случае работать с динамическими строками :-) Цель была сделать конструктор noexcept, чтобы такой неидиоматичный API как в picojson оправдать под слабым козырем что «некоторые исключения ключами компилятора выключают» :-) Т.е. если этот неидиоматичный API для того, чтобы использовать его там, где исключения выключаются, то parse() должна быть с noexcept - нет исключений - это значит нет исключений, а это noexcept :-) Ну если тебе интеллекта не хватило const char* msg_ поменять на std::string в Error, раз тебе динамические строки нужны, то причём тут смайлик? :-)

При этом стоит напомнить про то, что все это происходит в топике, где сравнивается производительность C++ относительно производительности C. А как раз из-за таких дополнительных накладных расходов в реальной жизни C++ный код немного, но проигрывает в скорости коду на C.

Стоит напомнить что все такие оценки от чудо-оптимизаторов цепепе-кода гроша ломаного не стоят, пока не будет предъявлены результаты профилировщика :-)

Итак, что мы видим в итоге: все тот же возврат строки из parse, но завернутый в никому ненужную обертку ради придури анонимного дебилоида.

В итоге мы видим явные намерения программиста, который свой API посвящает любителям отключать исключения, а не ту несуразицу, где в качестве ошибки возвращается объекта класса, вообще для этого не предназначенный :-)

anonymous
()
Ответ на: комментарий от anonymous

Цель была сделать конструктор noexcept

Вы тупой, поэтому повторю еще раз: вы не знаете, что такое noexcept и что с ним делать.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Что здесь будет происходить в STL-е, в котором для std::string нет small string optimization? А будет вызов new для создания строки, содержащей всего один ноль-символ.

Если уж до такой крайности доходить, что думать о таком «STL-е», то твой любимый цепепе лучше вообще не трогать палкой на расстоянии, а взять C :-)

Но все это херня по сравнению с тем, что в picojson вообще нет никаких накладных расходов на возврат пустого std::string. Ведь у авторов picojson нет смайликов в мозгах, поэтому им нет необходимости оборачивать std::string в никому не нужный здесь runtime_error.

У авторов picojson если неидиоматичный API, из-за чего, их либу лучше не трогать палкой на расстоянии :-)

В случае с runtime_error от дурносмайлика пользователь parse должен помнить, что проверить содержимое возвращенного runtime_error нужно с помощью какой-то левой функции really_error, лежащей совсем в другом пространстве имен.

В случае с runtime_error компилятор страхует от таких недоразумений, как std::cout << parse(..) :-) [Конечно, нормальный человек здесь подумает, что программист хочет вывести результат парсинга в cout, но это не про picojson :-) Лол :-)] Ты про безопасность типов слыхал что-нибудь вообще? :-) Или ты только new нулевых строк озабочен? :-)

Короче говоря, мне больше не интересно тут дискуссировать с тобой :-) У нас слишком разные подходы и точки зрения :-) Тем более, что ты нормально общаться не можешь, а у меня есть дела и по-важнее :-) Всего хорошего :-)

anonymous
()
Ответ на: комментарий от anonymous

Всего хорошего

неа, ты неполовозрелый отрок, поэтому всегда будешь приходить сюда и вновь что-то писать) не выебывайся (;

anonymous
()
Ответ на: комментарий от eao197

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

anonymous
()
Ответ на: комментарий от eao197

Что здесь будет происходить в STL-е, в котором для std::string нет small string optimization? А будет вызов new для создания строки, содержащей всего один ноль-символ.

http://en.cppreference.com/w/cpp/error/runtime_error

explicit runtime_error( const std::string& what_arg );    (1)
explicit runtime_error( const char* what_arg );           (2)    (since C++11)

Я плох в крестах, но там вызовется второй конструктор, нет?

anonymous
()
Ответ на: комментарий от anonymous

Если уж до такой крайности доходить, что думать

Идеально.

у меня есть дела и по-важнее Всего хорошего

Уходи и не возвращайся.

RazrFalcon ★★★★★
()
Ответ на: комментарий от anonymous

Я плох в крестах, но там вызовется второй конструктор, нет?

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

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Стоит напомнить что все такие оценки от чудо-оптимизаторов цепепе-кода гроша ломаного не стоят, пока не будет предъявлены результаты профилировщика :-)

В профайлер заглянете сами, а вот микробенчмарки показывают, что чудес не бывает. Лучшие результаты показаны под ArchLinux в виртуалке:

[     DONE ] ParseImit.picojson_approach(...) (669.353500 ms)
[   RUNS   ]        Average time: 66935.350 us
                         Fastest: 63999.950 us (-2935.400 us / -4.385 %)
                         Slowest: 71109.950 us (+4174.600 us / +6.237 %)

             Average performance: 14.93979 runs/s
                Best performance: 15.62501 runs/s (+0.68522 runs/s / +4.58657 %)
               Worst performance: 14.06273 runs/s (-0.87706 runs/s / -5.87063 %)
...
[     DONE ] ParseImit.smiley_approach(...) (846.955500 ms)
[   RUNS   ]        Average time: 84695.550 us
                         Fastest: 81682.950 us (-3012.600 us / -3.557 %)
                         Slowest: 94063.950 us (+9368.400 us / +11.061 %)

             Average performance: 11.80700 runs/s
                Best performance: 12.24246 runs/s (+0.43546 runs/s / +3.68816 %)
               Worst performance: 10.63107 runs/s (-1.17593 runs/s / -9.95961 %)
Худшие — на реальном железе под Win-10 и VC++14.0:
[     DONE ] ParseImit.picojson_approach(...) (1629.377980 ms)
[   RUNS   ]        Average time: 162937.798 us
                         Fastest: 160088.936 us (-2848.862 us / -1.748 %)
                         Slowest: 168252.857 us (+5315.059 us / +3.262 %)
                                  
             Average performance: 6.13731 runs/s
                Best performance: 6.24653 runs/s (+0.10922 runs/s / +1.77955 %)
               Worst performance: 5.94344 runs/s (-0.19388 runs/s / -3.15897 %)
...
[     DONE ] ParseImit.smiley_approach(...) (4794.915283 ms)
[   RUNS   ]        Average time: 479491.528 us
                         Fastest: 464195.658 us (-15295.870 us / -3.190 %)
                         Slowest: 498557.685 us (+19066.157 us / +3.976 %)
                                  
             Average performance: 2.08554 runs/s
                Best performance: 2.15426 runs/s (+0.06872 runs/s / +3.29513 %)
               Worst performance: 2.00579 runs/s (-0.07976 runs/s / -3.82426 %)

Так что в зависимости от платформы, компилятора и STL ваш вариант с возвратом runtime_error может или просто сосать, или сосать с проглотом.

ЗЫ. Код бенчмарков здесь.

ЗЗЫ. Для тех, кто переживает по поводу кормления тролля: просто воспользовался случаем попробовать один из фреймворков для микробенчмарков из вот этой статьи. Прикольной штукой оказался hayai, header-only, причем время компиляции сильно не увеличивает.

eao197 ★★★★★
()
Ответ на: комментарий от RazrFalcon

Уходи и не возвращайся.

Зачем же так неуважительно-то? Мне, например, приведённые доводы всех собеседников помогли сделать для себя определённый вывод о языке Си++. Чем больше будет различных точек зрения на обсуждаемый вопрос, тем лучше, так как чем шире кругозор, тем больше вероятность принять верное решение в нужное время, а не мчаться с невероятной скоростью к собственному краху.
Например, пару недель назад сотрудники «Ростелекома» принесли мне домой свою телевизионную приставку для просмотра Инет-телевидения. Люди так увлеклись созданием этих приставок, что даже не видят, что многим людям они вообще не нужны! Мне, например, больше помогли бы плагин для «Коди» или программа для «умного» телевизора «Филипс» и для «яблочной» ТВ-приставки, которые уже установлены и прекрасно работают. «Ростелекомовцам» в самый раз помог бы независимый взгляд со стороны, например, людей, смотрящих «Нетфликс».
Я хочу сказать, что проявив немного уважения к собеседнику и приняв его мнение, можно хорошенько осмотреться вокруг и затем уже принимать взвешенное решение. Отказываться от Крестов прямо сейчас никто никого не призывает, это дело каждого из нас.

Enthusiast ★★★
()
Ответ на: комментарий от tailgunner

Если хочешь, то можно удалить название конторы. Я там не работаю.

Enthusiast ★★★
()
Ответ на: комментарий от Enthusiast

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

Ой, да ладно. Только в этом треде как минимум трое категорически против C++ настроены. Да и я сам один из тех, кто призывает не трогать C++, если только нет четкой уверенности в том, что приемлемой альтернативы нет.

eao197 ★★★★★
()
Ответ на: комментарий от Enthusiast

Неуважительно? Человек неадекват, и на лоре, к счастью, моралфагов мало.

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

RazrFalcon ★★★★★
()
Ответ на: комментарий от eao197

Ой, да ладно. Только в этом треде как минимум трое категорически против C++ настроены. Да и я сам один из тех, кто призывает не трогать C++, если только нет четкой уверенности в том, что приемлемой альтернативы нет.

Когда ведущего игродела приставок «Сони» Майка Эктона спросили на выступлении на «Cppcon 2014» о том, почему он выбрал Си++ вместо Си, если при разработке игр он с товарищами не использует исключения, шаблоны, динамическое распознавание типов данных, потоки ввода-вывода Си++, стандартную библиотеку и перегрузку операторов, то он ответил, что лично он сам предпочёл бы использовать Си-99, а выбрать Си++ пришлось лишь из-за того, что в последние 20 лет был повышенный интерес к Си++ в обществе. Выходит, что количество числом побеждает качество.

Enthusiast ★★★
()
Ответ на: комментарий от Enthusiast

не использует исключения, шаблоны, динамическое распознавание типов данных, потоки ввода-вывода Си++, стандартную библиотеку и перегрузку операторов

Ты не мог бы процитировать, где он это сказал?

он ответил, что лично он сам предпочёл бы использовать Си-99

И это тоже.

tailgunner ★★★★★
()
Ответ на: комментарий от Enthusiast

Выходит, что количество числом побеждает качество.

Понять бы еще что вы подразумеваете под «качеством».

eao197 ★★★★★
()
Ответ на: комментарий от Enthusiast

Он сказал дальше, что они иногда избегаю функций C98, и что они будут использовать функции будущих стандартов C++ если они приносят пользу, а не просто так. Они использую C++ потому что в любой момент, когда надо они смогут использовать его функции, а не потому что он там людей больше. И у них проблема не day-to-day разработки, а низкоуровневая работа с embedded системой, потому что они делают игровой движок, но и это не говорит о том что там нельзя использовать C++. Достаточно посмотреть на CryEngine или что то подобное, они так же используют вкрапления C для низкоуровневых вещей, чтобы добавить производительности. Важно понимать, что есть такая вещь как оптимизация под архитектуру.

impowski
()
Ответ на: комментарий от tailgunner

Ты не мог бы процитировать, где он это сказал?

Про неиспользование шаблонов и прочего Майк говорит с 8-й минуты по 11-ю. Ответы на вопросы из зала начинаются с 1 часа 12-ти минут выступления, а вопрос о том, почему бы не использовать Си вместо Си++ был задан на 1-м часу 23-й минуте доклада.

Enthusiast ★★★
()
Ответ на: комментарий от Enthusiast

Про неиспользование шаблонов и прочего Майк говорит с 8-й минуты по 11-ю

То есть _цитаты_ не будет? Насколько я понимаю, он говорит о том, что использование шаблонов не поощряется.

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

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от eao197

Понять бы еще что вы подразумеваете под «качеством».

Высокая производительность работы исполняемого кода - таково позиционирование Крестов среди языков высокого уровня.
Игродел Майк Эктон же показывает, что по производительности Си уделывает Си++, а использование последнего лишь дань общественному мнению.

Enthusiast ★★★
()
Ответ на: комментарий от Enthusiast

Игродел Майк Эктон же показывает, что по производительности Си уделывает Си++

Чушь.

использование последнего лишь дань общественному мнению.

Так конкретная цитата будет?

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Помогу

https://youtu.be/rX0ItVEVjHc?t=1h23m51s

Упрощенная транскрипция:

- What is rationality behind c++, why just not go with c?
- My personal preference would be c99 for sure, but...rationality is really cultural. Over last 15 years c++ has become culturally dominant, and so we accept that, and so we work with it

Midael ★★★★★
()
Ответ на: комментарий от Enthusiast

Давно смотрел это выступление. Удивило дикое ЧСВ у ТС. Особенно когда он отвечал на вопросы. Что нивелировало все выступление.

RazrFalcon ★★★★★
()
Ответ на: комментарий от Enthusiast

Игродел Майк Эктон же показывает, что по производительности Си уделывает Си++

где показывает ? как показывает ?

anonymous
()
Ответ на: комментарий от Enthusiast

А теперь давай что-нибудь из отцов Unreal Engine. А то дохуя вас тут балаболов без опыта реальной разработки и с однобокими фактами наперевес.

anonymous
()
Ответ на: комментарий от Enthusiast

Высокая производительность работы исполняемого кода - таково позиционирование Крестов среди языков высокого уровня.

Ну и что с этим не так? Сравните производительность C++ с производительностью других ЯВУ, особенно мейнстримовых. Хотя бы с Java и C#. Неужели у C++ будет низкая производительность?

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

Во-первых, как я вижу, вы не показали, что Майк Эктон говорил именно об этом. Во-вторых, можно ли считать C языком такого же высокого уровня, как C++?

В-третьих, вы, похоже, не понимаете, что предлагает C++ своим пользователям. Он предлагает a) возможность построения абстракций с очень невысокими накладными расходами на эти абстракции, и b) возможность, при необходимости, опускаться на самый низкий уровень для того, чтобы устранять узкие места такими же способами, как это делается в C.

eao197 ★★★★★
()
Ответ на: комментарий от Enthusiast

Вчера Вася у подъезда сказал что лишп обогнал Си на синтетике числодробилок. Еще сказал много умных слов, но я не все запомнил. Пруфов тоже особо не было, но ты же понял что это рпавда?

anonymous
()
Ответ на: комментарий от eao197

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

anonymous
()
Ответ на: комментарий от anonymous

Таких сейчас очень много, как мне кажется.

eao197 ★★★★★
()
Ответ на: комментарий от Enthusiast

Высокая производительность работы исполняемого кода - таково позиционирование Крестов среди языков высокого уровня.

Мало того, что цепепе по уровню едва ли выше, чем Си, так ещё и его адепты даже имеющиеся примитивные механизмы абстракции, такие как классики, и то не применяют. Вот смотри. Выше было предложено для ошибок использовать класс Error, потому что использовать для этого std::string можно, но глупо, т.к. это игнорирует даже те самые механизмы абстракций, которые цепепе и отличают от Си. Истерика от этого классика потом перешла к появлению на свет доморощенных бенчмариков, которые демонстрируют как std::string обгоняет по скорости конструирования std::runtime_error. Из чего можно сделать вывод, что вместо throw std::runtime_error следует писать throw std::string, ведь быстрее же. Хотя зачем эти накладные расходы, когда можно отключать исключения... Т.е. даже те «высокоуровневые» средства, которые и есть в цепепе, самими же цепепешниками либо не используются, либо они их избегают и боятся, либо критикуют. Такие дела. :-)

anonymous
()
Ответ на: комментарий от anonymous

Привет, маминхуй. Врядли поймешь, но все же: цэпепешники использут те фичи, которые в данный момент удовлетворят требовани проекта/части проекта/модуля. Захотят удобства, используют все, что нужно, потребуется скорость - напишут С-подобную кэш-френдли портянку. Хотя... Тусуй колоду,

anonymous
()
Ответ на: комментарий от anonymous

Ну надо же, смайлик попрощался, но вернулся вновь.

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

Маленькая проблемка: предложенный класс Error имел говнореализацию. Даже вот такая реализация не имела бы проблем вашего класса Error:

class parsing_result {
  std::string desc_;
public :
  parsing_result(const parsing_result &) = default;
  parsing_result(parsing_result &&) = default;
  parsing_result(std::string desc) : desc_(move(desc)) {}

  bool success() const { return desc_.empty(); }
  const std::string & error_desc() const { return desc_; }
};

Истерика от этого классика потом перешла к появлению на свет доморощенных бенчмариков, которые демонстрируют как std::string обгоняет по скорости конструирования std::runtime_error.

Да какие проблемы? Предложите недоморощенные, aka промышленного качества, бенчмарки.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Маленькая проблемка: предложенный класс Error имел говнореализацию.

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

Даже вот такая реализация не имела бы проблем вашего класса Error:

Эта реализация демонстрирует то, что цепепе ты знаешь не очень хорошо, а ещё стиль не очень: Смотри:

// эти строчки не нужны, компилятор сгенерирует сам.
parsing_result(const parsing_result &) = default;
parsing_result(parsing_result &&) = default;

// эти функции-члены можно объявить noexcept.
// особенно тем, кто считает микросекунды в своих бенчмариках.
bool success() const { return desc_.empty(); }
const std::string & error_desc() const { return desc_; }

anonymous
()
Ответ на: комментарий от anonymous

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

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

Эта реализация демонстрирует то, что цепепе ты знаешь не очень хорошо

Еще раз для совсем тупых: я не эксперт в C++ и никогда не декларировал, что знаю C++ хорошо.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

Остаётся только пожать плечами. Как тогда можно на кого-то наезжать и судить о решениях других, не имея возможности оценить их ни эмпирической, ни экспертной оценкой?..

anonymous
()
Ответ на: комментарий от anonymous

Как тогда можно на кого-то наезжать и судить о решениях других, не имея возможности оценить их ни эмпирической, ни экспертной оценкой?..

Во-первых, варианту смайлика с его классом Error была предъявлена конкретная претензия: этот класс в принципе на поддерживает работу с динамическими строками (в отличии от подхода, примененного в picojson). Вам нужны какие-то экспертные и/или эмпирические оценки для того, чтобы понять состоятельность или несостоятельность этой претензии?

Во-вторых, здесь были предъявлены результаты замеров. Что в этих результатах не устраивает? Где какие-либо другие результаты?

Или вам нужны мнения «признанных экспертов», а своей головой вы думать не приучены?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Во-первых, варианту смайлика с его классом Error была предъявлена конкретная претензия: этот класс в принципе на поддерживает работу с динамическими строками

Перед ним никто не ставил задачу написать класс Error с динамическими строками.

(в отличии от подхода, примененного в picojson).

Подход не правильный - std::string не предназначен олицетворения ошибки.

Вам нужны какие-то экспертные и/или эмпирические оценки для того, чтобы понять состоятельность или несостоятельность этой претензии?

Конечно, ведь суть представленного класса Error была не в том, чтобы решить внезапно возникшую задачу генерации динамических строк, а в том, что он просто демонстрировал вариацию правильного подхода, а не того, что в picojson. Претензии к классу Error, который не содержит копию string, а содержит указатель на char, в данном случае просто выглядит как придирка на почве личной неприязни.

Во-вторых, здесь были предъявлены результаты замеров. Что в этих результатах не устраивает? Где какие-либо другие результаты?

Там результаты сравнения string с runtime_error, а не с Error смайлика.

Или вам нужны мнения «признанных экспертов», а своей головой вы думать не приучены?

Так я своей головой подумал и дал свою оценку твоему классу Error.

anonymous
()
Ответ на: комментарий от anonymous

Перед ним никто не ставил задачу написать класс Error с динамическими строками.

Слив. Смайлик говорил, что он может сделать «правильнее», чем picojson. А picojson возвращает динамические строки.

Подход не правильный - std::string не предназначен олицетворения ошибки.

Какие ваши доказательства?

Там результаты сравнения string с runtime_error, а не с Error смайлика.

Напомню, что смайлик кричал про возврат runtime_error и таки привел в качестве решения проблемы вариант с runtime_error. Что говорит о признании им правомочными претензий к качеству реализации класса Error.

Так я своей головой подумал и дал свою оценку твоему классу Error.

Я не предоставлял своей реализации класса Error. Вы бредите.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Эта реализация демонстрирует то, что цепепе ты знаешь не очень хорошо, а ещё стиль не очень: Смотри:

// эти строчки не нужны, компилятор сгенерирует сам.
parsing_result(const parsing_result &) = default;
parsing_result(parsing_result &&) = default;

Специально для улыбчивых дебилоидов и им сочувствующим приоткрою немного суровую правду жизни: до сих пор в эксплуатации находятся C++компиляторы, которые не полностью поддерживают стандарт C++11. В частности, не генерируют move-constructor и move-operator по умолчанию. К таким компиляторам, например, относятся Visual C++ 11.0 и 12.0.

Если не указывать в описании класса двух процитированных выше строчек, то с такими «нестандартными» компиляторами нарываешься на использование копирование вместо перемещения. А вот если эти две строки указать, то возникает ошибка времени компиляции (на примере VC++12.0):

t1.cpp(8) : error C2610: 'parsing_result::parsing_result(parsing_result &&)' : is not a special member function which can be defaulted

Понятно, что дебилам, которые ничего не видят за пределами уютного мирка конкретного дистрибутива Linux-а это все не интересно. Но вот если занимаешься кроссплатформенной разработкой, то с такими вещами приходится считаться и подстраховываться.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Слив. Смайлик говорил, что он может сделать «правильнее», чем picojson. А picojson возвращает динамические строки.

О динамических строках имело бы смысл говорить, если бы parse() возвращала распарсенную строку. Но parse() в picojson возвращает сущность класса std::string, состояние которой является всего лишь индикатором успешного парсинга (пустая строка) или возникшей ошибки (сообщение об ошибке). Сущности Error от смайлика олицетворяют именно ошибки и содержат сообщения в виде строковых литералов. Слива нет.

Какие ваши доказательства?

Отсутствие типизации. Объект std::string может означать что угодно - это просто строка. А семантически, вот это

std::string parse(..);
// или
try {
  // ...
} catch (std::string& error) {
}
никак не может быть яснее, чем вот это
std::runtime_error parse(..);
// или
try {
  // ...
} catch (std::runtime_error& error) {
}

Напомню, что смайлик кричал про возврат runtime_error и таки привел в качестве решения проблемы вариант с runtime_error. Что говорит о признании им правомочными претензий к качеству реализации класса Error.

runtime_error он привёл потому, что это стандартный класс, как и string, а не его доморощенный Error.

Я не предоставлял своей реализации класса Error. Вы бредите.

А это что? http://www.linux.org.ru/forum/development/12649936?cid=12661944 (комментарий)

anonymous
()
Ответ на: комментарий от eao197

до сих пор в эксплуатации находятся C++компиляторы, которые не полностью поддерживают стандарт C++11

И ты, конечно, публиковал свой код на ЛОРе именно с учётом этого факта. Ну, ок.

Если не указывать в описании класса двух процитированных выше строчек, то с такими «нестандартными» компиляторами

Для демонстрации намерений лучше придерживаться стандарта. На то он и стандарт.

Понятно, что дебилам, которые ничего не видят за пределами уютного мирка конкретного дистрибутива Linux-а это все не интересно.

А причём тут дистр линуха, если gcc и clang есть везде. Ну, кроме тех мест, где есть только «нестрандартные компиляторы» :-)

anonymous
()
Ответ на: комментарий от anonymous

О динамических строках имело бы смысл говорить, если бы parse() возвращала распарсенную строку.

Б**дь, что это за дебилизм на марше?!!! Да посмотрите вы в прототип функции parse из picojson наконец:

template <typename Iter> inline Iter parse(value& out, const Iter& first, const Iter& last, std::string* err)...
  
inline std::string parse(value& out, const std::string& s)...

inline std::string parse(value& out, std::istream& is)...
Все функции помещают результат разбора в out-параметр типа picojson::value. А возвращаемое значение либо указывает, что в out лежит корректное значение, либо содержит динамически созданное описание ошибки.

В этом плане использование std::string в качестве результирующего значения ничем не отличается от возврата int, long или какого-то другого типа.

Сущности Error от смайлика олицетворяют именно ошибки и содержат сообщения в виде строковых литералов.

Афигеть, дайте два. Вы тоже дебил или старательно стараетесь им казаться?

Объект std::string может означать что угодно - это просто строка.

Значение типа int (которое возвращается очень многими функциями стандартной библиотеки и стандарта POSIX) может означать что угодно — это просто знаковое целое. Тем не менее, спокойно используется для индикации ошибки.

А семантически

А семантически мы говорим о том, что picojson может использоваться в ситуациях, когда исключения просто-напросто запрещены. Поэтому апеляции к try-catch является лишь индикацией дебилизма говорящего. Ну или политкорректно: непонимания предмета.

А это что?

Ну и где там класс Error? Более того, где я предлагал использовать класс parsing_result? Речь шла о том, что у даже у такой тривиальной реализации parsing_result не было бы проблем смайликовского класса Error.

Или вы нашли еще какие-то фатальные проблемы у класса parsing_result?

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

И ты, конечно, публиковал свой код на ЛОРе именно с учётом этого факта. Ну, ок.

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

Как эти две строчки влияют на: а) производительность результирующего кода, b) на понятность кода и с) на сопровождаемость кода?

Иными словами: а не докопались ли вы до столба?

А причём тут дистр линуха, если gcc и clang есть везде.

ЧТД, за пределами уютненького мира конкретного дистрибутива линуха ничего видеть не хотим.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Б**дь, что это за дебилизм на марше?!!! Да посмотрите вы в прототип функции parse из picojson наконец:

Посмотрел...

В этом плане использование std::string в качестве результирующего значения ничем не отличается от возврата int, long или какого-то другого типа.

Правильно, но зачем тогда нужен C++ с его возможностями типизации, если эти возможности в упор игнорировать, ограничиваясь лишь фундаментальными типами или типами стандартной библиотеки?

Значение типа int (которое возвращается очень многими функциями стандартной библиотеки и стандарта POSIX) может означать что угодно — это просто знаковое целое. Тем не менее, спокойно используется для индикации ошибки.

Тогда зачем parse() в picojson возвращает «динамически созданное описание ошибки», если фундаментальные типы аж в POSIX «спокойно используется для индикации ошибки»?

А семантически мы говорим о том, что picojson может использоваться в ситуациях, когда исключения просто-напросто запрещены.

Тогда «динамически созданное описание ошибки» - это излишество, лучше ограничиваться фундаментальными типами.

Ну и где там класс Error? Более того, где я предлагал использовать класс parsing_result? Речь шла о том, что у даже у такой тривиальной реализации parsing_result не было бы проблем смайликовского класса Error.

Ну это Error с другим именем и по-другому названными функциями-членами.

Или вы нашли еще какие-то фатальные проблемы у класса parsing_result?

Да, конечно. Самая фатальная проблема у класса parsing_result в том, что хотя класс громко и назван «parsing_result», там нет самого результата парсинга, а есть лишь сообщение об ошибке.

anonymous
()
Ответ на: комментарий от eao197

Иными словами: а не докопались ли вы до столба?

Ну ты же докопался до того, что в Error смайлика const char*, а не std::string в качестве члена. Почему бы и мне не докопаться до лишних строк в объявлении? :-) Я просто показал, что докопаться к мелочам можно ко всему и у всех. Но это смысла лишено. И не продуктивно. Работать нужно над фундаментальными проблемами, а не заморачиваться над мелочёвкой, которой в C++, увы, пруд пруди.

anonymous
()
Ответ на: комментарий от anonymous

Ну ты же докопался до того, что в Error смайлика const char*, а не std::string в качестве члена.

Ваш Error ведет к утечками памяти.

Почему бы и мне не докопаться до лишних строк в объявлении? :-)

Повторю вопрос: к каким проблемам ведут эти две лишних строки?

Я просто показал, что докопаться к мелочам можно ко всему и у всех.

С каких пор утечки памяти стали мелочами?

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Правильно, но зачем тогда нужен C++ с его возможностями типизации, если эти возможности в упор игнорировать, ограничиваясь лишь фундаментальными типами или типами стандартной библиотеки?
Тогда зачем parse() в picojson возвращает «динамически созданное описание ошибки», если фундаментальные типы аж в POSIX «спокойно используется для индикации ошибки»?

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

1. Решь шла не про то, нужен ли C++ или не нужен. Речь шла о том, чтобы сделать решение лучше, чем в picojson-ом. Где это решение?

2. По поводу «если эти возможности в упор игнорировать, ограничиваясь лишь фундаментальными типами или типами стандартной библиотеки?» претензии нужно предъявлять смайлику, который предложил возвращать runtime_error.

3. По поводу «зачем parse() в picojson возвращает «динамически созданное описание ошибки»,»: в результате парсинга JSON-а принято иметь в качестве результата либо успешно разобранный JSON-документ, либо индикацию неудачи разбора + описание причины неудачи. Описание причины неудачи естественным образом представляется в виде динамически созданной строки.

4. По поводу «Тогда «динамически созданное описание ошибки» - это излишество, лучше ограничиваться фундаментальными типами.»: да не вопрос, просто покажите как. А потом мы разберем насколько ваш вариант лучше варианта из picojson.

5. По поводу «Самая фатальная проблема у класса parsing_result в том, что хотя класс громко и назван «parsing_result», там нет самого результата парсинга, а есть лишь сообщение об ошибке.»: вы либо забыли про метод parsing_result::success(), либо под результатом парсинга понимаете что-то другое. Что именно?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Ваш Error ведет к утечками памяти.
С каких пор утечки памяти стали мелочами?

Тот Error рассчитан на работу с литералами. Утечка будет, если в конструктор Error передать new char. Так что не передавай.

Повторю вопрос: к каким проблемам ведут эти две лишних строки?

Они ведут к соответствующей оценке кода. Раз автор их указал, значит автор не знает стандартные умолчания, что в свою очередь значит, что автор - не эксперт.

Да, кстати, твои success() и error_desc() (если правильно помню) можно и нужно объявлять noexcept, раз уж ты так щепетильно к накладным расходам относишься.

anonymous
()
Ответ на: комментарий от eao197

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

Просто тебе больше делать нечего, видимо.

1. Решь шла не про то, нужен ли C++ или не нужен. Речь шла о том, чтобы сделать решение лучше, чем в picojson-ом. Где это решение?

Опять ты не понял? Предложенное решение типобезопасное. Этим оно уже лучше и оправдывает использование C++ по назначению, опираясь на его сильную сторону - компиляцию.

2. По поводу «если эти возможности в упор игнорировать, ограничиваясь лишь фундаментальными типами или типами стандартной библиотеки?» претензии нужно предъявлять смайлику, который предложил возвращать runtime_error.

Вообще-то речь изначально шла об идиоматичном способе сообщений об ошибках в C++. Смайлик говорил, что для ошибок нужно использовать исключения. Ну и просто предложил вместо throw runtime_error, написать return runtime_error. И это выглядит логично.

Описание причины неудачи естественным образом представляется в виде динамически созданной строки.

Точно так же можно сказать, что «причины неудачи естественным образом представляются в виде строкового литерала, либо кода в виде целого числа».

4. По поводу «Тогда «динамически созданное описание ошибки» - это излишество, лучше ограничиваться фундаментальными типами.»: да не вопрос, просто покажите как. А потом мы разберем насколько ваш вариант лучше варианта из picojson.

Поменяй string на int в качестве возврата из parse(). Но это больше стиль C. В C++ принято уже давно исключения использовать.

5. По поводу «Самая фатальная проблема у класса parsing_result в том, что хотя класс громко и назван «parsing_result», там нет самого результата парсинга, а есть лишь сообщение об ошибке.»: вы либо забыли про метод parsing_result::success(), либо под результатом парсинга понимаете что-то другое. Что именно?

До тебя как-то туго доходит. Либо ты делаешь класс «описание ошибки», т.е. error_description, или error; либо ты делаешь класс «результат парсинга». Под результатом парсинга я понимаю объект JSON, с которым можно работать через функции и методы, т.е. твоими же словами: «в результате парсинга JSON-а принято иметь в качестве результата либо успешно разобранный JSON-документ».

anonymous
()
Ответ на: комментарий от anonymous

Конечно, ты просто выдрал фразу об отказе от использования исключений

Не ври, я отвечал на конкретное «язык должен использоваться либо полностью, либо никак».

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Тот Error рассчитан на работу с литералами. Утечка будет, если в конструктор Error передать new char. Так что не передавай.

Два вопроса:

1. Как Error защищает пользователя от ситуации, когда в конструктор Error по ошибке передается указатель на динамически созданную строку?

2. Если parse возвращает смайликовский Error с указателями на статические строковые литералы внутри, то как parse сможет вернуть описание возникшей ошибки парсинга? Например, что-то вроде: «в строке 10 не закрыта фигурная скобка, открытая в строке 9». Ведь picojson-овский парсер спокойно выдает такие описания.

Они ведут к соответствующей оценке кода. Раз автор их указал, значит автор не знает стандартные умолчания, что в свою очередь значит, что автор - не эксперт.

Автор не эксперт. Автор знает, что стандартные умолчания не работают в некоторых широкоиспользуемых C++ных компиляторах. Автору никто пока не показал, в чем именно состоит проблема с наличием двух этих строк.

Да, кстати, твои success() и error_desc() (если правильно помню) можно и нужно объявлять noexcept, раз уж ты так щепетильно к накладным расходам относишься.

Обоснуйте. В особенности для error_desc.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Предложенное решение типобезопасное. Этим оно уже лучше и оправдывает использование C++ по назначению, опираясь на его сильную сторону - компиляцию.

В чем заключается типобезопасность? Почему Error или runtime_error вы считаете более типобезопасными, чем std::string? Почему, по вашему мнению, использование std::string ведет к неоправданному применению C++?

Вообще-то речь изначально шла об идиоматичном способе сообщений об ошибках в C++. Смайлик говорил, что для ошибок нужно использовать исключения. Ну и просто предложил вместо throw runtime_error, написать return runtime_error. И это выглядит логично.

Перечитайте еще раз обсуждение. Идиоматический способ с исключениями не работает в ситуациях, когда исключения запрещены (и есть прикладные ниши, где исключения запрещены). В таких ситуациях идиоматично использовать возвращаемые значения. Использование return runtime_error вместо return string не логично, ибо, как уже показывалось ранее:

- работа с runtime_error в этом случае будет строится на точно таких же принципах, как и работа со string. Т.е. успех или неуспех определяется пустотой строки с описанием ошибки. Те же яйца, только с разных ракурсов;

- заворачивание текстового описания ошибки в runtime_error приводит к росту накладных расходов.

Т.е. принцип тот же, расходов больше. Так в чем логика?

Поменяй string на int в качестве возврата из parse().

Прекрасно. Как получить описание ошибки в случае ошибки парсинга?

В C++ принято уже давно исключения использовать.

Повторю в надцатый раз: есть ниши, где исключения не используются. В таких нишах picojson может применяться, а вот RapidJSON, в котором исключения бросаются, не может. Для таких ниш picojson отличный выбор. Для других ниш можно выбирать другие библиотеки.

Либо ты делаешь класс «описание ошибки», т.е. error_description, или error; либо ты делаешь класс «результат парсинга». Под результатом парсинга я понимаю объект JSON, с которым можно работать через функции и методы, т.е. твоими же словами: «в результате парсинга JSON-а принято иметь в качестве результата либо успешно разобранный JSON-документ».

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

Ну и еще раз: покажите уже вариант parse, который был бы лучше чем parse из picojson.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

1. Как Error защищает пользователя от ситуации, когда в конструктор Error по ошибке передается указатель на динамически созданную строку?

Никак. Он не предназначен для работу с ними. Автор Error, который решил не работать с динамическими строками не станет добавлять лишние проверки. Пользователи Error осведомляются в документации, что «const char* - указатель на литерал, передача new char ведёт к утечке памяти».

2. Если parse возвращает смайликовский Error с указателями на статические строковые литералы внутри, то как parse сможет вернуть описание возникшей ошибки парсинга? Например, что-то вроде: «в строке 10 не закрыта фигурная скобка, открытая в строке 9». Ведь picojson-овский парсер спокойно выдает такие описания.

Это наглядно демонстрирует всю порочность подхода picojson. Ну и что делать с таким описанием какому-нибудь инструментальному средству или редактору, чтобы, например, подсветить ошибку в тексте? Парсить строку с описанием ошибки чтобы вычленить позиции? «Замечательно» просто. Т.е., ещё раз, string не предназначен для олицетворения ошибки. Он сгодится для описания части ошибки, но не для ошибки в целом. В целом же в каждом случае должен быть специальный объект для этого. И runtime_error и Error смайлика не подходит в данном случае для этого также.

Обоснуйте. В особенности для error_desc.

Что обосновывать, если данные методы в принципе не могут генерировать исключения? Значит нужно дать подсказку компилятору для оптимизации.

anonymous
()
Ответ на: комментарий от eao197

В чем заключается типобезопасность? Почему Error или runtime_error вы считаете более типобезопасными, чем std::string?

В том, что любой функции, которая принимает string в качестве аргумента можно передать сущность более конкретной природы - «ошибка парсинга JSON». Под Error здесь надо понимать Json::Error. Компилятор соответствующим образом страхует от недоразумений.

Почему, по вашему мнению, использование std::string ведет к неоправданному применению C++?

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

Перечитайте еще раз обсуждение. Идиоматический способ с исключениями не работает в ситуациях, когда исключения запрещены (и есть прикладные ниши, где исключения запрещены). В таких ситуациях идиоматично использовать возвращаемые значения. Использование return runtime_error вместо return string не логично, ибо, как уже показывалось ранее:

Прочитай мой довод насчёт парсинга строки ошибки для вычленения ошибки из строки. Теперь у меня есть стопроцентная уверенность, что просто string абсолютно непригоден как класс для ошибок.

Прекрасно. Как получить описание ошибки в случае ошибки парсинга?

Описание с конкретной позицией ошибки? Никак. Описание «произошла ошибка» - элементарно. Не мне тебя учить.

Повторю в надцатый раз: есть ниши, где исключения не используются. В таких нишах picojson может применяться, а вот RapidJSON, в котором исключения бросаются, не может. Для таких ниш picojson отличный выбор. Для других ниш можно выбирать другие библиотеки.

Ок.

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

Некогда мне писать сюда ещё и код.

anonymous
()
Ответ на: комментарий от anonymous

Он не предназначен для работу с ними. Автор Error, который решил не работать с динамическими строками не станет добавлять лишние проверки. Пользователи Error осведомляются в документации, что «const char* - указатель на литерал, передача new char ведёт к утечке памяти».

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

Попробуйте, ради хохмы, переделать вот этот простейший код под использование смайликовского Error:

std::string imit_parse( long & value, long limit )
{
	auto u = (value / 2) * 3 + (value % 5);
	if( u > limit )
	{
		const auto old = value;
		value = u - limit;
		return fmt::format( "value {} produces too large result: {}, limit: {}",
				old, u, limit );
	}
	else
	{
		value = u;
		return std::string();
	}
}
Просто попробуйте.

Это наглядно демонстрирует всю порочность подхода picojson.

Так я нигде и не говорил, что у picojson офигеть какой правильный подход. Всего лишь просил и прошу показать, как сделать лучше, оставаясь в рамках определенных условий.

И runtime_error и Error смайлика не подходит в данном случае для этого также.

О том и речь. Смайлик смеялся над возвратом string-а, но то, что он предложил, объективно еще хуже.

Что обосновывать, если данные методы в принципе не могут генерировать исключения?

Кто вам сказал?

Приведенный мной вариант parsing_result имеет одну фундаментальную проблему, на которую никто из критиков не обратил внимания, хотя она была на поверхности: ничто не мешает пользователю вызвать error_desc, даже если парсинг завершился нормально и описания ошибки нет. За такое использование error_desc нужно бить пользователя по рукам. В этом случае error_desc может иметь, например, такой вид:

const std::string & error_desc() const {
  if( success() )
#if HAVE_EXCEPTIONS
    throw std::runtime_error( "error_desc is not available for successful result" );
#else
    std::abort();
#endif
  return desc_;
}

Значит нужно дать подсказку компилятору для оптимизации.

У компилятора и так достаточно информации для оптимизации. noexcept используются для несколько других вещей.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

В том, что любой функции, которая принимает string в качестве аргумента можно передать сущность более конкретной природы - «ошибка парсинга JSON». Под Error здесь надо понимать Json::Error. Компилятор соответствующим образом страхует от недоразумений.

Эту сущность, как я понимаю, вы сами придумали. Вам хочется, чтобы picojson возвращал некую структуру с детализированным описанием ошибки. Авторам picojson этого не хотелось. Пользователям picojson, как я понимаю, это так же не нужно. Их вполне устраивает возврат string-а.

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

Но виноват, конечно, C++.

Некогда мне писать сюда ещё и код.

А как дышал, как дышал. Звиздеть каждый может. А как код показать, так фейлы вроде смайликовых.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Попробуйте, ради хохмы, переделать вот этот простейший код под использование смайликовского Error:

Мне не надо пробовать, я прекрасно понимаю, что литералы имеют статическую природу. Error смайлика для ошибок вида «неправильно составленная строка JSON» или «в строке JSON присутстуют недопустимые символы».

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

Лучше - это структурированный error. Если исключения прям уж нельзя, то ещё лучше - это parse_result с error и json_obj на борту. И всё это можно сделать без потерь производительности. Код показывать не буду.

О том и речь. Смайлик смеялся над возвратом string-а, но то, что он предложил, объективно еще хуже.

Лучше с т.з. типовой безопасности.

Приведенный мной вариант parsing_result имеет одну фундаментальную проблему, на которую никто из критиков не обратил внимания, хотя она была на поверхности: ничто не мешает пользователю вызвать error_desc, даже если парсинг завершился нормально и описания ошибки нет.

Ничего аномального конкретно здесь не вижу. Предложенная лапша с макросами - это костыль. Фундаментальная проблема - это отказ от исключений.

У компилятора и так достаточно информации для оптимизации. noexcept используются для несколько других вещей.

Ну озвучь уже наконец для каких это «других вещей».

anonymous
()
Ответ на: комментарий от eao197

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

Именно структурированный Error.

Авторам picojson этого не хотелось. Пользователям picojson, как я понимаю, это так же не нужно. Их вполне устраивает возврат string-а.

Меня не устраивает, поэтому picojson использовать не буду.

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

На их взгляд.

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

На твой взгляд.

Но виноват, конечно, C++.

Так и есть :-)

Звиздеть каждый может. А как код показать, так фейлы вроде смайликовых.

К тебе это тоже относится, судя по числу комментариев.

anonymous
()
Ответ на: комментарий от anonymous

Error смайлика для ошибок вида «неправильно составленная строка JSON» или «в строке JSON присутстуют недопустимые символы».

Поэтому возврат экземпляров смайликовского Error — это говно. У них есть проблемы, которых нет у std::string.

Лучше - это структурированный error.

Именно. Но ведь смайлик этого не показал.

Лучше с т.з. типовой безопасности.

Не понимаю. Покажите кейс, где смайликовские варианты будут типобезопаснее, чем string.

Фундаментальная проблема - это отказ от исключений.

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

Ну озвучь уже наконец для каких это «других вещей».

Мне от этого какая выгода?

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

На твой взгляд.

Мой взгляд подтвержден перечислением реальных проблем и замерами производительности. Попробуйте опровергнуть чему-нибудь подобным.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Поэтому возврат экземпляров смайликовского Error — это говно.

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

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

Пусть, например, библиотеку вроде picojson ещё можно собрать и с поддержкой исключений. При этом API с исключениями использует API без исключений. Теперь сравни:

void throw_error(std::string&&);
и
void throw_error(Json::Error&&);
В 1-ю ф-ю можно передать любой string. Во 2-ю - только Json::Error. Включается в дело аппарат типов, нельзя случайно передать «» в throw_error. А ещё throw_error можно перегружать разными типами ошибок, мало ли для чего.

Мне от этого какая выгода?

Зачем тогда вообще общаться?

anonymous
()
Ответ на: комментарий от eao197

Мой взгляд подтвержден перечислением реальных проблем и замерами производительности.

Это вовсе не означает, что другим это должно быть интересно.

Попробуйте опровергнуть чему-нибудь подобным.

Это никому не будет интересно.

anonymous
()
Ответ на: комментарий от anonymous

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

Нет. Есть библиотека, которая может выдавать динамически формируемые сообщения. Есть заявления анонима о том, что он может сделать лучше. По факту лучше не получается. Более того, приходится удалять часть уже имеющейся в библиотеки функциональности (отказываться от динамически сформированных описаний). И, плюс к тому, нужно соблюдать осторожность при работе со смайликовским классом Error:

- нельзя туда передавать указатель на динамически созданную строку;

- нельзя туда передавать указатель на временный буфер.

Все это грабли, которые возникают из-за неправильного использования C++.

Т.е. речь не о том, что в picojson хороший подход и этот подход нельзя сделать лучше. Речь о том, что предложенные варианты имеют проблемы.

Пусть, например, библиотеку вроде picojson ещё можно собрать и с поддержкой исключений.

А если бы у бабушки...

В очередной раз повторю простую вещь: смайлик заявил, что он мог бы сделать лучше, чем это сделано в picojson. Но не сделал, т.к. в обоих решениях есть серьезные недостатки. Хотя от этих недостатков можно было бы легко избавиться. Простейший набросок класса, который не имеет проблем смайликовского Error и накладных расходов runtime_error я уже показывал.

Отсюда мораль: язык C++ позволяет делать нормальные типобезопасные и нересурсоемкие решения. То, что эти решения где-то не применяются — это следствие либо принятых разработчиком проектных решений (см. на picojson в котором возвращается string, в которым автор не счел нужным в крохотной библиотеке выстраивать дополнительные типы), либо врожденного дебилизма (см. смайликовский Error).

Зачем тогда вообще общаться?

Общаться и обучать — это несколько разные вещи.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Это вовсе не означает, что другим это должно быть интересно.

Объективные критерии не интересны? Ну okay.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

не надоело кормить явного неадеквата? Или это спортивный интерес с целью «нащупать дно»?

anonymous
()
Ответ на: комментарий от anonymous

Опыт показывает, что после таких holy wars очень просто общаться с эффективными менеджерами. Некоторые из них ведут себя очень похожим образом.

Так что скорее это прокачивание определенных скилов :)

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Есть библиотека, которая может выдавать динамически формируемые сообщения. Есть заявления анонима о том, что он может сделать лучше. По факту лучше не получается.

Есть библиотека, в которой применяется специфический и очень спорный подход в части возвращемого значения parse(). Смайлик пытался показать порочность этого подхода. Ну а то, что он не сделал в качестве члена данных string, а сделал const char*, можно с очень большой натяжкой назвать то, что он не сделал лучше. Да, динамические строки ошибок Error смайлика не может.

Все это грабли, которые возникают из-за неправильного использования C++.

Обсуждать понятие «неправильного использования C++» можно бесконечно, в данном случае, начинать надо с отказа от исключений и создания типов данных пользования. Я не вижу «неправильного использования C++» в классе Error смайлика. Используется так, как используется. Просто «нужно соблюдать осторожность при работе со смайликовским классом Error», твоим же словами.

Простейший набросок класса, который не имеет проблем смайликовского Error и накладных расходов runtime_error я уже показывал.

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

либо врожденного дебилизма (см. смайликовский Error).

Это уже звучит с твоей стороны как самозащита на пустом месте.

Общаться и обучать — это несколько разные вещи.

Так я и не прошу меня обучать. Я сказал, что success() и error_desc() в твоём классе нужно объявить noexcept потому что они не генерируют исключений. И не важно, что API позиционируется для использования в условиях отсутствия исключений, и, как следствие, отсутствия try/catch и отсутствия веток выполнения обработки исключений. Важно показать пользователю в сигнатуре максимум информации.

anonymous
()
Ответ на: комментарий от anonymous

Есть библиотека, в которой применяется специфический и очень спорный подход в части возвращемого значения parse().

Именно так. Причем тут очень бы не помешало учесть мнение автора библиотеки и сценарии, под которые библиотека разрабатывалась. Возможно, термин «очень спорный» не следует использовать, а нужно оставить только «специфический».

Ну а то, что он не сделал в качестве члена данных string, а сделал const char*, можно с очень большой натяжкой назвать то, что он не сделал лучше.

Ровно до тех пор, пока кто-нибудь не наступит на эти грабли. Так что это не натяжка, это именно что грабли.

Да, динамические строки ошибок Error смайлика не может.

О том и речь.

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

О том и речь: минимальные изменения, но результат качественно другой. В этом и есть проблема C++: не имея головы на плечах даже нормальную идею можно превратить в грабли, на которые обязательно кто-нибудь наступит. И, что важно, предотвратить эти грабли совсем не сложно.

Это уже звучит с твоей стороны как самозащита на пустом месте.

Нет, у меня уже есть опыт общения с этим персонажем. Как только смайлик выкатывает код, так сразу в этом коде обнаруживаются проблемы.

Я сказал, что success() и error_desc() в твоём классе нужно объявить noexcept потому что они не генерируют исключений.

noexcept нужно ставить тогда, когда принципиально важно, что методы не генерируют исключений. Например, если это move-operator или функция swap. В остальных случаях все не так однозначно. И если по поводу success еще можно согласиться с использованием noexcept, то с error_desc все не так просто.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Ровно до тех пор, пока кто-нибудь не наступит на эти грабли. Так что это не натяжка, это именно что грабли.

Так пусть не наступают. Это не проблемы смайлика.

Нет, у меня уже есть опыт общения с этим персонажем. Как только смайлик выкатывает код, так сразу в этом коде обнаруживаются проблемы.

Концептуальной проблемы в Error смайлика нет. Есть потенциальная проблема, если какой-то лапух передаст в его Error динамически созданный буфер. А не надо передавать.

anonymous
()
Ответ на: комментарий от anonymous

Концептуальной проблемы в Error смайлика нет. Есть потенциальная проблема, если какой-то лапух передаст в его Error динамически созданный буфер. А не надо передавать.

Т.е. все просто: не надо делать ошибок в программе?

Сколько вам лет, уважаемый?

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

где в качестве ошибки возвращается объекта класса, вообще для этого не предназначенный :-)

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

DarkEld3r ★★★★★
()
Ответ на: комментарий от eao197

Т.е. все просто: не надо делать ошибок в программе?

C++ ошибок не прощает. Да и ты сам говорил, «это C++, надо хоть немного знать».

Сколько вам лет, уважаемый?

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

anonymous
()
Ответ на: комментарий от anonymous

C++ ошибок не прощает.

Именно поэтому в C++ добавляют средства для того, чтобы воспрепятствовать появлению ошибок. Игнорировать их — это не есть признак большого ума.

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

Судя по тому, что вы пишете, у вас достаточно опыта, чтобы думать, что вы бы использовали бы смайликовский Error без проблем. Но недостаточно, чтобы понять, что это заблуждение. И вы ошибетесь рано или поздно. А уж ваши коллеги ошибутся еще быстрее.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Игнорировать их — это не есть признак большого ума.

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

Но недостаточно, чтобы понять, что это заблуждение. И вы ошибетесь рано или поздно. А уж ваши коллеги ошибутся еще быстрее.

Это голословно. Не надо мне рассказывать обо мне и моих коллегах. Я тут типа аноним :-)

anonymous
()
Ответ на: комментарий от anonymous

Так и тут.

Да, да, вот это, по-вашему мнению, нормальный вариант:

Error parse(...) {
  ...
  if(somethig_wrong)
    return Error(fmt::format("something is going wrong: {}", msg).c_str());
  ...
}

Ну okay.

Виноват-то все равно C++ окажется.

Это голословно.

Подобных утверждений я наслушался вдоволь. И деятелей, которые делают подобные утверждения насмотрелся.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Да, да, вот это, по-вашему мнению, нормальный вариант:

Это вариант «прострела ноги». Нормальный вариант:

Error parse(...) {
  ...
  if(somethig_wrong)
    return Error("something wrong");
  ...
}

Подобных утверждений я наслушался вдоволь. И деятелей, которые делают подобные утверждения насмотрелся.

Теперь твой счётчик «подобных утверждений» и деятелей, которые делают «подобные утверждения», увеличился ещё на 1.

anonymous
()
Ответ на: комментарий от anonymous

Это вариант «прострела ноги». Нормальный вариант:

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

То, что вы здесь вдвоем защищаете, вообще не нуждается в работе со строками и/или указателями на строки. Можно обойтись обычным enum-ом:

enum class parsing_result {
  ok,
  something_wrong,
  ...
};
const char * strresult(parsing_result r) {
  switch(r) {
    case parsing_result::ok: return "no error";
    case parsing_result::something_wrong: return "something wrong";
    ...
  }
  return "unknown error";
}
...
parsing_result parse(...) {
  ...
  if(something_wrong()) return parsing_result::something_wrong;
  ...
}
И никаких проблем ни с динамическими строками, ни с временными буферами.

Ну и да, strresult можно пометить как noexcept, если компилятор поддерживает noexcept.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

Вот именно, я использую C++. Использую в своих целях, использую так, как считаю нужным. Ну прям как авторы picojson.

То, что вы здесь вдвоем защищаете, вообще не нуждается в работе со строками и/или указателями на строки. Можно обойтись обычным enum-ом:

Да, можно. Но тогда для каждой ошибки придётся пополнять enum, пополнять strresult(), т.е., как говорят там у них, это «error prone». А защищаю я здесь типовую безопасность, как я уже сказал.

И никаких проблем ни с динамическими строками, ни с временными буферами.

Да, действительно.

Ну и да, strresult можно пометить как noexcept, если компилятор поддерживает noexcept.

Ну наконец-то.

anonymous
()
Ответ на: комментарий от anonymous

А защищаю я здесь типовую безопасность, как я уже сказал.

Сдается мне, ваши понятия о типобезопасности и способах ее достижения находятся очень далеко от моих.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Но тогда для каждой ошибки придётся пополнять enum, пополнять strresult(), т.е., как говорят там у них, это «error prone».

Кстати говоря, при работе с enum class современные компиляторы C++ становятся все умнее и умнее: https://godbolt.org/g/4OB1mo

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Кстати говоря, при работе с enum class современные компиляторы C++ становятся все умнее и умнее: https://godbolt.org/g/4OB1mo

А Страуструп об этом писал ещё в своей TC++PL 3rd в контексте обычных enum. Было это в 1998, 18 лет назад.

anonymous
()
Ответ на: комментарий от eao197
switch(r) {
    case parsing_result::ok:

ещё бы перестали требовать имя перечисления в такой ситуации

next_time ★★★★★
()
Ответ на: комментарий от anonymous

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

Ну не так уж очень.

DarkEld3r ★★★★★
()
Ответ на: комментарий от eao197

noexcept нужно ставить тогда, когда принципиально важно, что методы не генерируют исключений. Например, если это move-operator или функция swap. В остальных случаях все не так однозначно.

И какие минусы могут быть от «лишних» noexcept? Случай когда они расставлены ошибочно, естественно, не интересен.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Но string вообще ни к месту.

С этим не спорю. Как по мне, лучше тогда применять optional и variant/Result, раз уж мы не хотим использовать исключения, а всё остальное костыли примерно одного порядка.

Хотя вон в бусте и используют выходной параметр функции под это дело, но там логика понятна - это именно запасной вариант, если не хочется обращаться к исключениям.

DarkEld3r ★★★★★
()
Ответ на: комментарий от anonymous

Но тогда для каждой ошибки придётся пополнять enum, пополнять strresult(), т.е., как говорят там у них, это «error prone»

Это ещё почему? Современные компиляторы умеют выдавать предупреждения, если какой-то кейс пропущен, так что после добавления значение в enum не получится забыть добавить описание.

Правда возвращать при этом «unknown error» не вижу смысла - если уж очень хочется, то такое значение стоит добавить и в enum.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Расставляя noexcept я фиксирую контракт своего класса. Например, написав однажды:

class parsing_result {
public :
  const std::string & error_desc() const noexcept {...}
  ...
};
убрать в дальнейшем noexcept при смене деталей работы parsing_result будет не просто. Т.к. ничто не скажет пользователям моего класса parsing_error, что noexcept исчез.

eao197 ★★★★★
()
Ответ на: комментарий от DarkEld3r

Это ещё почему? Современные компиляторы умеют выдавать предупреждения, если какой-то кейс пропущен, так что после добавления значение в enum не получится забыть добавить описание.

В любом случае, это дополнительная работа. Кого-то смущают накладные расходы на этапе выполнения, меня же смущают накладные расходы на сопровождение, в первую очередь.

anonymous
()
Ответ на: комментарий от eao197

убрать в дальнейшем noexcept при смене деталей работы parsing_result будет не просто.

Ты написал изначально не так:

const std::string & error_desc() const noexcept {...}
а так:
const std::string & error_desc() const noexcept { return desc_; }
И ты ссылку на данные возвращаешь, не может быть там исключения. Конечно, если не рвать себе на голове волосы, предполагая какое-нибудь кэширование в mutable-член данных в const-методе, о котором любят писать эксперты в своих книжках.

anonymous
()
Ответ на: комментарий от anonymous

Кого-то смущают накладные расходы на этапе выполнения, меня же смущают накладные расходы на сопровождение, в первую очередь.

Я правильно понимаю - возврат чистого Error, проверку которого можно пропустить и компилятор ничего не скажет, уменьшает накладные расходы на сопровождение?

tailgunner ★★★★★
()
Ответ на: комментарий от eao197

Т.к. ничто не скажет пользователям моего класса parsing_error, что noexcept исчез.

Да, аргумент.

DarkEld3r ★★★★★
()
Ответ на: комментарий от tailgunner

Я правильно понимаю - возврат чистого Error, проверку которого можно пропустить и компилятор ничего не скажет, уменьшает накладные расходы на сопровождение?

Нет, ты не правильно понимаешь. (Только не бань меня больше.) Правильно эмитировать исключение Error.

anonymous
()
Ответ на: комментарий от anonymous

Ты написал изначально не так:

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

И ты ссылку на данные возвращаешь, не может быть там исключения.

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

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

В любом случае, это дополнительная работа.

Конкретно эта работа с очень большой вероятностью «окупается»: все описания в одном месте находиться будут, а не размазаны по коду - исключается (уменьшается) вероятность добавить «почти такое же описание».

Опять же, по вариантам енума клиент логику строить может и если мы изменяем/добавляем что-то, то оно на этапе компиляции отвалится. А вот изменение строк пройдёт незамеченным, да и вообще с ними работать неудобно, если требуется что-то ещё кроме как вывести ошибку.

DarkEld3r ★★★★★
()
Ответ на: комментарий от eao197

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

Вот как было написано изначально: https://www.linux.org.ru/forum/development/12649936?cid=12661944 (комментарий)

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

Как видно из первоначального варианта, error_desc() объявлена встроенной. В публичном интерфейсе засветилась и сама реализация. Так что там поневоле появляются знания о работе кода (из одной инструкции).

anonymous
()
Ответ на: комментарий от DarkEld3r

Конкретно эта работа с очень большой вероятностью «окупается»: все описания в одном месте находиться будут, а не размазаны по коду - исключается (уменьшается) вероятность добавить «почти такое же описание».

Иногда централизация - это хорошо, иногда - плохо.

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

Для этого лучше структурированный Error, а не enum.

anonymous
()
Ответ на: комментарий от anonymous

Конечно, если не рвать себе на голове волосы, предполагая какое-нибудь кэширование в mutable-член данных в const-методе, о котором любят писать эксперты в своих книжках.

Подожди! Но ведь весь C++ именно об этом!!11

LamerOk ★★★★★
()
Ответ на: комментарий от anonymous

В публичном интерфейсе засветилась и сама реализация.

Специально для дебилов: реализация, пусть даже inline-функций, не может рассматриваться в качестве интерфейса или деталей интерфейса.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Для этого лучше структурированный Error, а не enum.

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

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Для этого лучше структурированный Error, а не enum.

Одно другому не мешает. Внутри этого «структурированного Error» вполне может быть значение из enum и метод для получения текста ошибки.

DarkEld3r ★★★★★
()
Ответ на: комментарий от LamerOk

Подожди! Но ведь весь C++ именно об этом!!11

Ну, как бы, да :-)

anonymous
()
Ответ на: комментарий от anonymous

Правильно эмитировать исключение Error.

Я думал, обсуждается

Error parse(...) {
  ...
  if(somethig_wrong)
    return Error("something wrong");
  ...
}
tailgunner ★★★★★
()
Ответ на: комментарий от eao197

Специально для дебилов: реализация, пусть даже inline-функций, не может рассматриваться в качестве интерфейса или деталей интерфейса.

С другой стороны, если const T& f() const объявлена встроенной, то делать её вдруг не встроенной - это значит признаться в своей недальновидности. А раз сделал встроенной, то такую функцию можно объявлять noexcept.

anonymous
()
Ответ на: комментарий от tailgunner

Я думал, обсуждается

Сейчас уже обсуждается noexcept, встроенность и контракты интерфейсов с пользователем.

anonymous
()
Ответ на: комментарий от anonymous

Мой вопрос был как раз о контракте интерфейса, ну да ладно.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

С другой стороны, если const T& f() const объявлена встроенной, то делать её вдруг не встроенной - это значит признаться в своей недальновидности.

Вы сделали мой день.

Отлейте в граните еще что-нибудь эпичное, пожалуйста.

А раз сделал встроенной, то такую функцию можно объявлять noexcept.

Пропробуйте-ка вот такую встроенную функцию объявить noexcept:

class T {
public :
  ... // all necessary constructors, copy- and move-operators.

  std::unique_ptr< T > clone() const {
    return std::make_unique<T>(*this);
  };
  ...
};

inline-овость функции не иметь ничего общего с noexcept.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Вы сделали мой день.
Отлейте в граните еще что-нибудь эпичное, пожалуйста.

Мило.

Пропробуйте-ка вот такую встроенную функцию объявить noexcept:

Причём тут эта функция, если я о (тобою же написанной)

const std::string& error_desc() const { return desc_; }
Не сможешь ты доказать, что noexcept тут использовать нельзя. А я смогу доказать, что можно, ибо это тут можно по определению.

anonymous
()
Ответ на: комментарий от anonymous

Еще раз для совсем уж дебилов: можно != нужно.

То, что можно поставить noexcept в данном конкретном случае не означает, что это нужно делать.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Еще раз для совсем уж дебилов: можно != нужно.
То, что можно поставить noexcept в данном конкретном случае не означает, что это нужно делать.

Но ведь нет причин не делать этого, ибо return desc_ не может привести к исключительной ситуации.

anonymous
()
Ответ на: комментарий от eao197

Причины должны быть для того, чтобы помечать метод/функцию атрибутом noexcept. А не наоборот.

Причина очевидна - оптимизация кода на уровне компилятора ценой набора 8 символов плюс пробел.

anonymous
()
Ответ на: комментарий от anonymous

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

Можно подумать здесь кто-то кого-то воспринимает всерьёз. Ты серьёзно?

anonymous
()
Ответ на: комментарий от anonymous

Ну так поведайте миру свою версию предназначения noexcept, скоростной вы наш.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

читаю и зло берёт насчёт спора про то, что лучше - Error или std::string. Оба варианта - шило. Ничего не нужно возвращать. Нужно передавать коллбэк, который будет вызываться с контекстом ошибки, а там уже тот, кто вызывает ваш парсинг разберётся, что ему с ошибкой делать. Накладных расходов, когда используются шаблоны - 0. Для сишечки будет один лишний дереференс адреса функции, которую нужно вызвать. Пример кода:

https://github.com/dzidzitop/libafc/blob/master/src/afc/json.hpp#L74

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

на сишечке будет также лишний аргумент функции (как и для шаблонов, но те скорее всего заинлайнятся). Но в любом случае это много лучше бесконечных проверок на эроры в формате free text.

а вообще «дорогие» эксепшены для этого придумали - эффективность кода должна повыситься, если явно эксепшен выкидывать на первом же факапе.

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

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

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

Пример кода:

А теперь пример использования покажи.

Ну и забавно смотрятся шаблоны щедро разбавленные goto.

DarkEld3r ★★★★★
()
Ответ на: комментарий от dzidzitop

goto? У тебя что рак мозга?

anonymous
()
Ответ на: комментарий от DarkEld3r

можешь представить обычный callback, который отвечает за обработку ошибок.

struct ErrorHandler
{
	void malformedJson(const char *pos) { throw parse_exception(); }
	void prematureEnd() { throw parse_exception(); }
}

можно протеговать функции как no_return для потенциально более компактного кода (без goto).

Там, где нельзя пользоваться исключениями, можно завести внутри флаг и аккуратно его передавать в сишном стиле. Тот код с goto как раз это и поддерживает, не исключая возможности кинуть исключение для обработчика ошибок.

а что не так с goto? дедушка ленин наказал не пользоваться?

dzidzitop ★★
()
Ответ на: комментарий от dzidzitop

можешь представить обычный callback, который отвечает за обработку ошибок.

Представить-то я представил, то выглядит это нефига не удобно, особенно если не брать исключения. На примере parseObject: случается у нас malformedJson - вызывается колбек, там мы устанавливаем флаг и потом его проверяем. Это однозначно менее удобно чем использование какого-нибудь Result или исключений.

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

а что не так с goto?

А какая в коде от них польза? Избавление от ретурнов посреди функции? Сомнительный выигрыш.

DarkEld3r ★★★★★
()
Ответ на: комментарий от dzidzitop

а что не так с goto? дедушка ленин наказал не пользоваться?

Теоретики структурного программирования Эдсгер Дейкстра и Никлаус Вирт против goto.

anonymous
()
Ответ на: комментарий от DarkEld3r

читаю и зло берёт насчёт спора про то, что лучше - Error или std::string. Оба варианта - шило. Ничего не нужно возвращать. Нужно передавать коллбэк, который будет вызываться с контекстом ошибки, а там уже тот, кто вызывает ваш парсинг разберётся, что ему с ошибкой делать.

Ты. Это. Серьезно?

tailgunner ★★★★★
()
Ответ на: комментарий от DarkEld3r

А какая в коде от них польза?

более компактный код на выходе для non-error веток выполнения. если бы там был только ретурн, то goto бы не было.

тот тулкит одинаково хорошо поддерживает как C++ with exceptions так и C++ without exceptions. поэтому решение оправдано. а возвращать Result - непонятно что там должно быть внутри и это может быть недёшево в случае глубокой вложенности места, где произошла ошибка.

dzidzitop ★★
()
Ответ на: комментарий от anonymous

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

dzidzitop ★★
()
Ответ на: комментарий от DarkEld3r

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

Кстати, этим тулкитом реализовал парсинг достаточно раскидистый json с массивами вложенных структур без единого new/malloc (среди прочего). он изначально на это затачивался, с сохранением возможности поддерживать код парсинга, а не на то, чтобы красивую диаграмму классов нарисовать. А если не думать про производительность, то любой вариант будет «достаточно хорош».

dzidzitop ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.