Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Но если уж и апеллировать к авторитетам, то в области алгоритмов C++ нужно ровняться на Степанова — он спокойно использует беззнаковые, и ЕМНИП даже рекомендовал в одной из лекций
Ну вот некоторое время назад был холивар как раз по поводу STL, и как она ужасна, и что "написал он ее в больнице, и не иначе, как то была больница Степанова-Скворцова ит.п.". Тут можно до бесконечности кидаться ссылками, конечно...
И меряться авторитетами основоположников тоже можно долго
EP>Использование знаковых целых, там где по смыслу подходят беззаконные (да ещё и имеют большую "ёмкость") — это что-то из области babysitting'а, причём не особо удачного. Если уж нужна нянька — то тогда уже брать safe int и им подобные.
Одна беда: если ты пишешь под фреймворк, где используются знаковые, то у тебя особого выбора нет. В чужой монастырь со своим уставом (даже не со своим, а со степановским)... Я бы вот предпочел использовать везде size_t, вроде для того оно и предназначалось, но, увы...
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
EP>>Но если уж и апеллировать к авторитетам, то в области алгоритмов C++ нужно ровняться на Степанова — он спокойно использует беззнаковые, и ЕМНИП даже рекомендовал в одной из лекций
. _>Ну вот некоторое время назад был холивар как раз по поводу STL, и как она ужасна, и что "написал он ее в больнице, и не иначе, как то была больница Степанова-Скворцова ит.п.".
STL одна из лучших библиотек которые я видел, я бы сказал даже лучшая
Что конкретно "ужасного" там?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>STL одна из лучших библиотек которые я видел, я бы сказал даже лучшая EP>Что конкретно "ужасного" там?
Не буду цитировать холиварщиков, тем более, что я не разделяю многие из их аргументов, гугл в помощь, если интересно. Вроде читал даже на КЫВТе сенсационный пост типа "Александреску опускает итераторы"
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
EP>>STL одна из лучших библиотек которые я видел, я бы сказал даже лучшая EP>>Что конкретно "ужасного" там? _>Не буду цитировать холиварщиков, тем более, что я не разделяю многие из их аргументов, гугл в помощь, если интересно. Вроде читал даже на КЫВТе сенсационный пост типа "Александреску опускает итераторы"
То решение которое он предлагает в D крайне спорное. Точнее оно отлично подходит для InpuntRange, а вот начиная с ForwardRange начинаются серьёзные проблемы. Всё подробно описано в этом топике
И, кстати, на эту тему недавно был доклад — там также отмечается, что хоть в некоторых крайне специфичных случаях D Range это удобно, но в общем случае менее мощное средство чем итераторы.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>То решение которое он предлагает в D крайне спорное. Точнее оно отлично подходит для InpuntRange, а вот начиная с ForwardRange начинаются серьёзные проблемы. Всё подробно описано в этом топике
Что до меня, то только то, что, в STL, к примеру, для копирования требуется не забыть переразмерить контейнер-приемник (вариант — не забыть использовать std::inserter), что std::remove на самом деле не удаляет, а просто перетасовывает элементы, и то, что большинство библиотечных алгоритмов принимают кучку однотипных аргументов (подходя формально — "bad smell" в чистом виде) — это все не есть достоинства.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
_>Что до меня, то только то, что, в STL, к примеру, для копирования требуется не забыть переразмерить контейнер-приемник (вариант — не забыть использовать std::inserter)
Для подобных вещей есть assign, insert, и те же *inserter'ы.
И что именно значит "не забыть"? Видимо "не забыть" означает "нужно знать что делает используемый инструмент, а не использовать его наугад" — тогда да, нужно
_>что std::remove на самом деле не удаляет, а просто перетасовывает элементы
Ничего удивительного — std::remove работает с range'ами, а не с контейнерами. Принял range, и возвратил range (точнее два).
_>и то, что большинство библиотечных алгоритмов принимают кучку однотипных аргументов (подходя формально — "bad smell" в чистом виде) — это все не есть достоинства.
однако нигде его не перехватываете.
ну и в целом всё убого- скорость O(N^2) вместо напрашивающихся O(n * log(n))
O>Условие: O>Даны 3 списка с числами. Числа в списках не повторяются. Сами списки отсортированы. Необходимо реализовать метод GetNext, который бы обходил все 3 списка и выдавал числа в порядке возрастания. Объединять списки нельзя! O>Примеры списков: O>[List]: 1, 5, 12, 28, 31 O>[List]: 6, 9, 13 O>[List]: 3, 7, 10, 15 O>Вывод в этом случае должен быть таким: O>GetNext << 1; O>GetNext << 3; O>GetNext << 5; O>GetNext << 6; O>GetNext << 7; O>GetNext << 9; O>и т.д.
O>Решение: O>
O>....
O>vector<vector<int>*> vectors;//тут хранятся наши списки
O>vector<int> vec1;
O>vector<int> vec2;
O>vector<int> vec3;//сами списки
O>....
O>vectors.push_back(&vec1);
O>vectors.push_back(&vec2);
O>vectors.push_back(&vec3);
O>vector<int> indexes(vectors.size(),0);//тут храним индекс элемента, который последний раз брали для каждого из списков
O>GetNext(indexes);
O>....
O>bool isExist(vector<int> &vec, int index)
O>{
O> return index < vec.size();
O>}
O>int GetNext( vector<int> &indexes)
O>{
O> int min = 0;
O> int index = -1;
O> for(int i=0;i<vectors.size();++i)
O> {
O> if(isExist(*vectors.at(i),indexes.at(i)))
O> {
O> min = vectors.at(i)->at(indexes.at(i));
O> index = i;
O> break;
O> }
O> }
O> if(index == -1)
O> throw exception();
O> for(int i=0;i<vectors.size();++i)
O> {
O> if(isExist(*vectors.at(i),indexes.at(i)))
O> {
O> if(vectors.at(i)->at(indexes.at(i))<min)
O> {
O> min = vectors.at(i)->at(indexes.at(i));
O> index = i;
O> }
O> }
O> }
O> indexes.at(index)++;
O> return vectors.at(index)->at(indexes.at(index)-1);
O>}
O>
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>И что именно значит "не забыть"? и пр.
Это означает, что оно не интуитивно понятно трудно для понимания начинающему. И есть мнение, что все это можно было сделать проще и безопаснее за счет незначительных накладных расходов.
_>>и то, что большинство библиотечных алгоритмов принимают кучку однотипных аргументов (подходя формально — "bad smell" в чистом виде) — это все не есть достоинства.
EP>Что значит "кучку однотипных аргументов"?
Здравствуйте, slava_phirsov, Вы писали:
_>И есть мнение, что все это можно было сделать проще и безопаснее за счет незначительных накладных расходов.
Например.
_>>>и то, что большинство библиотечных алгоритмов принимают кучку однотипных аргументов (подходя формально — "bad smell" в чистом виде) — это все не есть достоинства. EP>>Что значит "кучку однотипных аргументов"? _>
_>4 аргумента. И можно перепутать аргументы местами, и это скомпилируется без проблем. Да, это один из видов "bad smell" — слишком много аргументов.
1. Четыре одинаковых итератора тут только в частном случае, а в общем — две пары разных итераторов.
2. Во всей библиотеке итераторы из одного range принимаются по порядку, запутаться трудно.
3. Какая альтернатива-то? Естественно без потери мощности в общем случае. Есть Boost.Range (или его аналог который войдёт в стандарт) — но это всего лишь оптимизация некоторых частных случаев.
EP>1. Четыре одинаковых итератора тут только в частном случае, а в общем — две пары разных итераторов.
Одна беда — поскольку типы итераторов являются параметрами шаблона, то типизация не помешает перепутать эти пары местами.
Что касается конкретно std::search, то ИМХО в большинстве случаев все четыре итератора будут одного типа.
EP>2. Во всей библиотеке итераторы из одного range принимаются по порядку, запутаться трудно.
Однако новички путаются. И даже — страшно сказать — забывают, надо ли ставить первым в паре begin или end. Да, со временем привыкают. Ну так о том и речь, что ножик-то слишком острый, чтобы намазывать им масло на хлеб, мог бы быть и потупее.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
EP>>1. Четыре одинаковых итератора тут только в частном случае, а в общем — две пары разных итераторов. _>Одна беда — поскольку типы итераторов являются параметрами шаблона, то типизация не помешает перепутать эти пары местами.
_>Что касается конкретно std::search, то ИМХО в большинстве случаев все четыре итератора будут одного типа.
Согласен.
EP>>2. Во всей библиотеке итераторы из одного range принимаются по порядку, запутаться трудно. _>Однако новички путаются. И даже — страшно сказать — забывают, надо ли ставить первым в паре begin или end. Да, со временем привыкают.
Код-то тестировать (или в крайнем случае проверять на нескольких входных данных вручную) нужно в любом случае, там всё и вылезет. Плюс есть же всякие debug итераторы и алгоритмы.
_>Ну так о том и речь, что ножик-то слишком острый, чтобы намазывать им масло на хлеб, мог бы быть и потупее.
Скоро будет в стандарте. А в библиотеках уже больше 10 лет.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
>3. Какая альтернатива-то? Естественно без потери мощности в общем случае. Есть Boost.Range (или его аналог который войдёт в стандарт) — но это всего лишь оптимизация некоторых частных случаев.
Аналог Boost.Range это https://github.com/ericniebler/range-v3 ? Выглядит многообещающе, еще бы попробовать их где-нибудь, но Visual C++ опять не поддерживается.
Блин, 15 лет прошло со времен плясок вокруг Visual C++ 6.0 в попытках заставить его компилировать шаблоны. Как будто ничего и не поменялось
Здравствуйте, PM, Вы писали:
>>3. Какая альтернатива-то? Естественно без потери мощности в общем случае. Есть Boost.Range (или его аналог который войдёт в стандарт) — но это всего лишь оптимизация некоторых частных случаев. PM>Аналог Boost.Range это https://github.com/ericniebler/range-v3 ?
Я не следил за предложениями, может там и другие proposals были.
PM>Блин, 15 лет прошло со времен плясок вокруг Visual C++ 6.0 в попытках заставить его компилировать шаблоны. Как будто ничего и не поменялось
Какое-то движение всё же есть. Они хоть и отстают, но уже стараются догонять.
Кстати, ЕМНИП Саттер (или Стефан) не так давно говорил, что они вот-вот начнут внутри компилятора использовать AST
P.S. Помимо Boost.Range ещё есть и аналог в Adobe.ASL
Здравствуйте, Evgeny.Panasyuk, Вы писали:
>>>3. Какая альтернатива-то? Естественно без потери мощности в общем случае. Есть Boost.Range (или его аналог который войдёт в стандарт) — но это всего лишь оптимизация некоторых частных случаев. PM>>Аналог Boost.Range это https://github.com/ericniebler/range-v3 ?
EP>Я не следил за предложениями, может там и другие proposals были.
Я тоже не слежу за предложениями, просто читаю http://ericniebler.com, Eric там пишет о своих успехах
PM>>Блин, 15 лет прошло со времен плясок вокруг Visual C++ 6.0 в попытках заставить его компилировать шаблоны. Как будто ничего и не поменялось
EP>Какое-то движение всё же есть. Они хоть и отстают, но уже стараются догонять. EP>Кстати, ЕМНИП Саттер (или Стефан) не так давно говорил, что они вот-вот начнут внутри компилятора использовать AST
Прогресс есть, реально в VS 2013 не хватет только constexpr из-за отсутствия которого самые современные библиотеки не поддерживаются. Я с Boost.Hana так пролетел, вот и ворчу
EP>P.S. Помимо Boost.Range ещё есть и аналог в Adobe.ASL
Да, только давненько оно не обновлялось.
Кстати недавно Eric победил проблему с производительностью counted ranges на которую указывал Sean Parent (я так понимаю он автор ranges в ASL). Результатом и стало предложение D4128 Ranges for the Standard Library: Revision 1. В нем помимо изменений в стандартной библиотеке предлагается немного поменять семантику range-based for loop чтобы begin и end могли быть разными типами. Так что в Visual C++ 2020 может быть увидим что-нибудь
Здравствуйте, Evgeny.Panasyuk, Вы писали:
К>>- сделать не на векторах, а по-честному, на списках К>>- на изменяемых списках это даже проще делается
EP>А зачем? Тормозить ведь будет. Это же не merge списков в один большой, а просто вывод по отдельности каждого элемента. EP>Вот если бы в результате нужен был список — то другое дело, действительно проще и быстрее собрать из трёх связанных списков один большой.
А с чего тормозить-то будет? Списки/векторы уже отсортированы, от них требуется только операция продвижения итератора вперёд.
Здравствуйте, alzt, Вы писали:
К>>>- сделать не на векторах, а по-честному, на списках К>>>- на изменяемых списках это даже проще делается EP>>А зачем? Тормозить ведь будет. Это же не merge списков в один большой, а просто вывод по отдельности каждого элемента. EP>>Вот если бы в результате нужен был список — то другое дело, действительно проще и быстрее собрать из трёх связанных списков один большой. A>А с чего тормозить-то будет? Списки/векторы уже отсортированы, от них требуется только операция продвижения итератора вперёд.
Линейный обход связного списка в общем случае на порядок(и) дороже чем соответствующий обход вектора. Если в задаче не указанно что нужен именно связный список, то по-умолчанию нужно брать vector.
Здравствуйте, PM, Вы писали:
PM>Прогресс есть, реально в VS 2013 не хватет только constexpr из-за отсутствия которого самые современные библиотеки не поддерживаются. Я с Boost.Hana так пролетел, вот и ворчу
Спасибо за ссылку.
Но ведь не побелил же! Его концепция CountedRange выглядит как хак, который к тому же жертвует производительностью. Если бы не было потерь производительности, то можно было бы и пережить, а с потерями — ну уж нет.
ИМХО, не нужно боятся вводить новые концепции Range'ей — если эти концепции чётко улавливают суть, позволяя писать эффективный код (в абсолютном смысле, а не "в этом вот примере всего 5%" разница). Не хаки-адапторы к старым алгоритмам, а полноценные range со своими оптимизированными алгоритмами, как раз наподобие partition_point_n.
PM>на которую указывал Sean Parent (я так понимаю он автор ranges в ASL).
Он, кстати, раньше работал со Степановым.
Кстати, вот в этом моменте Степанов рассказывает про Counted Range.
А вот тут про двумерные итераторы (Eric упоминал их как segmented).