Здравствуйте, so5team, Вы писали:
ЕМ>>Но удобство C++ как раз в том, что на нем можно писать всё. S>Евгений, блин, уже лет 20 как пора забыть про эту чушь.
Почему? Разве есть что-то, что невозможно написать на C++?
Здравствуйте, so5team, Вы писали:
S>Простите, что сделали в C++11?
Добавили пользовательские литералы. Правда, задачу создания таблиц строк вида "длина+текст" это все равно не решает, приходится извращаться, как и раньше.
Здравствуйте, karbofos42, Вы писали:
BFE>>Т.е. интерфейс (как базовый класс) вам был не нужен? Да? А ничего , что это совершенно два разных подхода к решению задачи? K>Мне нужно удобство, информативность и всякие там контроли типов.
Ну так возьмите vector и пользуйте.
K>Затем, что там методы на вставку элементов называются у контейнеров по-разному и auto с шаблонами не прокатят, придётся городить что-то на итераторах или ещё какие занимательные конструкции писать.
Зачём вам что-то сложнее вектора?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Добавили пользовательские литералы. Правда, задачу создания таблиц строк вида "длина+текст" это все равно не решает, приходится извращаться, как и раньше.
Здравствуйте, пффф, Вы писали:
П>Можно. Но зачем? То же самое можно сделать и без всякой вирутальности. Я так понимаю, у тебя претензия к тому, что нет в стандартных контейнерах метода add, причем тут виртуальность, я не очень понял
В итоге приходим к тому, что в STL для контейнеров есть пара соглашений, типа методов begin() и end(), которые возвращают итераторы, благодаря которым в язык добавили "сахар" вида "for (auto &v : items)".
Есть подобное счастливое стечение обстоятельств, по которым метод size наверно везде одинаково называется и этим можно воспользоваться в шаблонах. Так себе решение, но ладно.
Для добавления такого не приключилось и потому тут мне набросали примеров с итераторами. Это и в плане кода объёмнее и я сомневаюсь, что будет быстрее работать, чем вызов виртуального метода, на котором сэкономили.
И вот теперь вопрос: опытные плюсовики в итоге у себя хардкодят конкретные контейнеры и не парятся о универсальности? Или заморачиваются и пишут эти все конструкции с итераторами?
Мне виртуальность не нужна как таковая. Просто коллекции в Java/C# за счёт общих интерфейсов мне видятся удобными.
В C++ же как-то с обратной стороны заходить нужно с добавлением элементов через итераторы, а не напрямую в коллекцию и непонятно что на выходе это даёт.
Здравствуйте, пффф, Вы писали:
П>Давайте примеры приводите
Чего именно примеры? В абзаце, после которого Вы это написали, минимум три разных утверждения.
П>В 8ми битный контроллер с килобайтом памяти нельзя запихнуть какую-то сложную задачу.
Если там два-три десятка килобайт под код, а килобайт-два — только под изменяемые данные, туда можно запихнуть достаточно сложные задачи.
Чтобы оценить реальную потребность в объеме кода для решения задачи, очень полезно поглядывать на демки (intro) размером в один-четыре килобайта, которые вместе с видео еще и музыку играют. Понятно, что там полно хакерских приемов, но важен порядок размера. Мне приходилось писать на ассемблерах предельно компактный/быстрый код, чтобы уложиться в аппаратные рамки, но перед этими ребятами я всегда снимаю шляпу — сам так не умею. Когда кто-то категорически утверждает "эту задачу невозможно решить такими средствами", надо сразу отсылать туда.
П>Надо будет — и на асме напишут.
На асме как раз проще, там все под контролем.
П>частенько разглядывают асмовский выхлоп от компилятора, и да, это часто делается превентивно.
Если так, то молодцы. В мейнстриме такого уже почти не встретишь. В большинстве случаев оно и не надо, но беда в том, что даже примерно оценивать разучились.
П>по идее, эти люди уже должны быть испорчены современным образованием
Если "их учили", то да (таких большинство). Если "они учились", то все зависит от личности и способностей.
П>>>Откуда ты знаешь про систему отбора?
ЕМ>>Из обсуждений собеседований на форумах.
П>А, ну тогда стопудово всё так и есть
Ну а откуда мне ее еще знать?
П>Надо просто знать язык, и представлять хоть немного, что получается из тез или иных конструкций
Если в основе этого понимания лежит "компилятор соптимизирует" (а сейчас это типично), то лишь явная нужда может заставить этим интересоваться.
Здравствуйте, пффф, Вы писали:
П>Не понял, о какой экономии ты говоришь, и почем add должен быть обязательно виртуальным? Можешь это объяснить?
Да хоть size, хоть empty, хоть любой другой метод.
Если у коллекций есть общий тип с этими методами, то можно написать нормальный метод, в котором их вызывать.
Не делать так я вижу только одну причину: экономия на обращениях к таблице виртуальных методов и т.п.
Вдруг кто-то будет миллионы записей перемалывать в векторе, а тут вызов empty() будет виртуальный.
На шаблонах частично можно перекрыться, но это всё равно больше как костыль выглядит.
П>А в чем проблема?
Многословно и некрасиво же, больше шансов выстрелить в ногу.
П>А с чего это будет работать медленнее?
Вместо прямого обращения к коллекции идёт прослойка в виде итератора, который и создать нужно и его методы дёрнуть.
Здравствуйте, B0FEE664, Вы писали:
ЕМ>>задачу создания таблиц строк вида "длина+текст" это все равно не решает, приходится извращаться, как и раньше.
BFE>А string_view на что?
Так все равно ж исходные литералы лежат отдельно, с нулями в конце, а рядом лежат ссылки на них в объектах string_view.
Здравствуйте, Евгений Музыченко, Вы писали:
BFE>>Что значит "принято"/"не принято"? C++ мультипарадигменный язык и стиль написания обычно зависит от квалификации программистов команды и их образования. ЕМ>Тем не менее, оценки вроде "это не настоящий C++" можно встретить повсеместно.
Никто не использует настоящий С++ просто потому, что его никто не знает.
ЕМ>Интересно, существуют подобные оценки для более других языков?
Да. Например, JavaScript. На JavaScript можно написать код, который будет изменять сам себя. Даже теоретических наработок написания таких приложений мало, что уж говорить о практике. Мне, например, только однажды довелось написать функцию, которая в рантайме порождала функцию, которая в рантайме создавала функцию ответной реакции на событие. Вроде и ничего сложного, но преодолеть инертность мышления и заставить себя писать код в таком стиле очень трудно.
Здравствуйте, karbofos42, Вы писали:
BFE>>Ну так возьмите vector и пользуйте. K>Потом все вызовы придётся переписывать, если захочется поменять вектор на множество или какой другой контейнер.
Два-три раза перепишете, а потом, глядишь, и шаблоны освоите...
BFE>>Зачём вам что-то сложнее вектора? K>По-моему контейнеры все достаточно простые
Простые. Ага. Покажешь коллеге константную ссылку на shared_ptr хранящий вектор shared_ptr'ов на объекты, так двумя руками креститься начинают.
K>и выбирают их под частые варианты использования через компромисс.
компромисс?
Здравствуйте, karbofos42, Вы писали:
K>Допустим, нужно сохранить коллекцию в json в виде массива [1,2,3] или что-то в этом духе. K>Методу записи просто нужно перебрать все элементы коллекции, получить их значения и записать в json. Вектор там или множество — вообще же без разницы. K>При чтении значений из json мне так же без разницы как там элементы хранятся, просто нужно их по очереди добавить в коллекцию.
Вы просто не понимаете, о чём пишите.
Если записать json ещё возможно (хотя не все это могут), то вот прочитать...
Не, не хочу снова писать про этот дрянной формат.
Здравствуйте, B0FEE664, Вы писали:
BFE>Никто не использует настоящий С++ просто потому, что его никто не знает.
И его не существует?
BFE>Мне, например, только однажды довелось написать функцию, которая в рантайме порождала функцию, которая в рантайме создавала функцию ответной реакции на событие. Вроде и ничего сложного, но преодолеть инертность мышления и заставить себя писать код в таком стиле очень трудно.
Я когда-то так писал под Clipper (компилятор кода в стиле FoxPro под DOS, но допускал и интерпретацию кода, созданного в ходе выполнения). Когда встроенных средств параметризации не хватало, приходилось извращаться с созданием конструкций на ходу. Никаких приятных воспоминаний это не оставило. Сколько боролись с самомодификацией кода, чтоб снова к ней вернуться.
Здравствуйте, karbofos42, Вы писали:
K>привёл наглядный пример, что в С++ принято делать всрато своеобразно, но быстро
C++ тем и хорош, что на нем можно делать "своеобразно и очень быстро", так и "единообразно и менее быстро" (хотя иногда и столь же быстро, оптимизаторы насобачились). Если в него и добавлять еще более единообразные абстракции, то лишь сбоку, чтоб подключались только по запросу.
K>экономя и на тех же виртуальных методах, на счёт которых у ТС вроде бы есть сомнения.
Не, у ТС сомнений как раз никогда не было. Сомнения у тех, кто никогда не интересовался, как работает механизм виртуальных вызовов, но "где-то слышал, что он сильно снижает быстродействие".
K>Да хоть size, хоть empty, хоть любой другой метод. K>Если у коллекций есть общий тип с этими методами, то можно написать нормальный метод, в котором их вызывать.
А сейчас что мешает написать общий код?
K>Не делать так я вижу только одну причину: экономия на обращениях к таблице виртуальных методов и т.п.
Да, и это веская причина
K>Вдруг кто-то будет миллионы записей перемалывать в векторе, а тут вызов empty() будет виртуальный.
Да. А ты думаешь, что миллионы записей перемалывать — очень редкий кейс?
В текущей ситуации вызов size'а будет только один, если контейнер не меняется в ходе работы. В случае виртуального size оптимизатор скорее всего не сможет доказать, что size всегда возвращает одно и то же, и будет честно дёрuать виртуальный size на каждой итерации
K>На шаблонах частично можно перекрыться, но это всё равно больше как костыль выглядит.
Нормально выглядит. Я не понимаю, что ты докопался до плюсов? Иди в шарповый форум, раз на шарпе пишешь, не надо предлагать переделать плюсики в шарп
П>>А в чем проблема?
K>Многословно
Не проблема
K>и некрасиво же,
Вполне красиво
K>больше шансов выстрелить в ногу.
И где же?
П>>А с чего это будет работать медленнее?
K>Вместо прямого обращения к коллекции идёт прослойка в виде итератора, который и создать нужно и его методы дёрнуть.
Там всё непосредственно вызывается/передаётся, оптимизаторы сто лет назад уже такое схлопывают
Здравствуйте, Евгений Музыченко, Вы писали:
П>>Давайте примеры приводите
ЕМ>Чего именно примеры? В абзаце, после которого Вы это написали, минимум три разных утверждения.
Примеры "промышленных, реально массовых, 8- и 16-разрядных МК", на которых всё сейчас сделано, как вы утверждаете.
Отвечайте последовательно, не надо заглядывать в следующий абзац, не обработав предыдущий. Или у вас спекулятивное осмысление?
И что именно вам не нравится в трех разных утверждениях? Я вообще много разных утверждений пишу, гораздо больше трёх
П>>В 8ми битный контроллер с килобайтом памяти нельзя запихнуть какую-то сложную задачу.
ЕМ>Если там два-три десятка килобайт под код, а килобайт-два — только под изменяемые данные, туда можно запихнуть достаточно сложные задачи.
Если есть десятки килобайт памяти программ, и килобайты ОЗУ — под это вполне можно писать на плюсах, и результат, скорее всего, будет компактнее и быстрее.
ЕМ>Чтобы оценить реальную потребность в объеме кода для решения задачи, очень полезно поглядывать на демки (intro) размером в один-четыре килобайта, которые вместе с видео еще и музыку играют. Понятно, что там полно хакерских приемов, но важен порядок размера. Мне приходилось писать на ассемблерах предельно компактный/быстрый код, чтобы уложиться в аппаратные рамки, но перед этими ребятами я всегда снимаю шляпу — сам так не умею. Когда кто-то категорически утверждает "эту задачу невозможно решить такими средствами", надо сразу отсылать туда.
Только не надо говорить, что все сишечники только такие.
П>>Надо будет — и на асме напишут.
ЕМ>На асме как раз проще, там все под контролем.
Только до-о-о-о-о-о-о-о-о-го
П>>частенько разглядывают асмовский выхлоп от компилятора, и да, это часто делается превентивно.
ЕМ>Если так, то молодцы. В мейнстриме такого уже почти не встретишь. В большинстве случаев оно и не надо, но беда в том, что даже примерно оценивать разучились.
Вот на днях читал на хабре какую-то статью, там чел двоичным поиском занимался, оптимизировал. На плюсах, с шаблонами, и прочим. И вполне смотрел выхлоп компилятора. Наверное, тоже бывший сишечник.
У сишечника, кстати, уверен, будет всё гораздо хуже в подобном случае.
П>>по идее, эти люди уже должны быть испорчены современным образованием
ЕМ>Если "их учили", то да (таких большинство). Если "они учились", то все зависит от личности и способностей.
А, это не настоящие шотландцы, я понял
П>>>>Откуда ты знаешь про систему отбора?
ЕМ>>>Из обсуждений собеседований на форумах.
П>>А, ну тогда стопудово всё так и есть
ЕМ>Ну а откуда мне ее еще знать?
Так может, тогда не надо ничего категорично утверждать, не имея достоверных сведений о предмете?
П>>Надо просто знать язык, и представлять хоть немного, что получается из тез или иных конструкций
ЕМ>Если в основе этого понимания лежит "компилятор соптимизирует" (а сейчас это типично), то лишь явная нужда может заставить этим интересоваться.
Приходится много кода писать. И да, обычно я использую разумные предположения, и считаю, что компилятор соптимизирует. Можно писать максимально оптимально, но тогда проект будет закончен через тысячу лет. Когда будет проблема с производительностью вылезать, тогда и будем разбираться. И проще запустить какой-нибудь профайлер, который покажет, где узкие места, чем писать всё "оптимально"
Здравствуйте, karbofos42, Вы писали:
K>Удобно ведь было бы в метод принимать просто коллекцию, получать какой-то абстрактный итератор для перебора или через виртуальный метод add добавить пару элементов.
Нет. Ну то есть задачи, где надо любую коллекцию принимать — это разве что перегонка в джсон какая-нибудь, ну там шаблончик один пишется и всё. В остальных случаях это не имеет никакого практического смысла. А накладные расходы на таскание указателя на ТВМ — очень серьёзные могут быть
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, karbofos42, Вы писали:
П>>Можно. Но зачем? То же самое можно сделать и без всякой вирутальности. Я так понимаю, у тебя претензия к тому, что нет в стандартных контейнерах метода add, причем тут виртуальность, я не очень понял
K>В итоге приходим к тому, что в STL для контейнеров есть пара соглашений, типа методов begin() и end(), которые возвращают итераторы, благодаря которым в язык добавили "сахар" вида "for (auto &v : items)". K>Есть подобное счастливое стечение обстоятельств, по которым метод size наверно везде одинаково называется и этим можно воспользоваться в шаблонах. Так себе решение, но ладно.
Это не счастливое стечение обстоятельств, это изначальный дизайн такой.
И из-за изначального дизайна нет и метода add у всех контейнеров, потому что он хз что должен делать. А некоторые контейнеры вообще не могут иметь некоторых методов. Вот чтобы делали методы push_front/push_back для стека или односвязанного списка? А ты предлагаешь, чтобы они были, как я понимаю, у god-объекта Object, от которого все наследуются. И что бы делали их реализации в наследниках? Ничего? Молча хавали данные и всё? Удачи в отладке. Или надо бросать исключение? Прощай, производительность. В C++ в общем-то всё тоже самое, только у него полиморфизм статический, и твоя программа просто не соберётся, и именно за это плюсики и любят.
K>Для добавления такого не приключилось и потому тут мне набросали примеров с итераторами. Это и в плане кода объёмнее и я сомневаюсь, что будет быстрее работать, чем вызов виртуального метода, на котором сэкономили.
Будет быстрее, будет
K>И вот теперь вопрос: опытные плюсовики в итоге у себя хардкодят конкретные контейнеры и не парятся о универсальности?
Когда как. Если что-то очень не устраивает по производительности — пишут свои контейнеры с заточкой под свои задачи. Это обычно удел контор типа Яндекса, или каких-нибудь САПРов. Остальным хватает стандартного, или из буста
K>Или заморачиваются и пишут эти все конструкции с итераторами?
Какая проблема с итераторами?
K>Мне виртуальность не нужна как таковая. Просто коллекции в Java/C# за счёт общих интерфейсов мне видятся удобными.
Мне коллекции C++ за счет одинаковых интерфейсов тоже видятся удобными. А если у разных коллекций разные интерфейсы, то наверное это не просто так, и я хочу сделать что-то странное, что, скорее всего, будет неоптимальным из-за неправильно выбранного контейнера.
K>В C++ же как-то с обратной стороны заходить нужно с добавлением элементов через итераторы, а не напрямую в коллекцию
Не вижу проблем. Более того, такое не слишком нужно. Ну не могут алгоритмы одинаково хорошо работать со всеми типами контейнеров. У каждого контейнера свои преимущества и недостатки, и их надо выбирать, исходя из решаемых задач. А у вас, как я понимаю, дерьмово выходит с любыми контейнерами. Зато — удобно.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Они использовали хотя бы миллионы разных классов? Таблица-то общая на весь класс, а в каждом объекте добавляется только ее адрес.
Почему это? Восемь лишних байт на класс в каждом экземпляре.
Здравствуйте, karbofos42, Вы писали:
K>Для добавления такого не приключилось и потому тут мне набросали примеров с итераторами. Это и в плане кода объёмнее и я сомневаюсь, что будет быстрее работать, чем вызов виртуального метода, на котором сэкономили.
Почему сомневаешься? Не знаешь, как работает инлайн?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте