Здравствуйте, archimag, Вы писали:
A>Здравствуйте, remark, Вы писали:
R>>1. более высокий уровень абстракции — я буду выражать языком программирования именно то, что хочу сказать, т.е. "выполнить поиск этого элемента в этом векторе", а не "выполнить поиск этого значения в этом диапазоне с начала вектора и до конца". Т.е. в такой ситуации мне совершенно не интересно знать про последовательности. Мне совершенно не интересно знать про функции begin() и end().
A>Понятие последовательности элементов, выражением которого являются итераторы, является более общим, чем понятие конкретного контейнера. Поэтому, более высоким уровнем абстракции является именно использование итераторов. Я обычно вообще не знаю, какой именно контейнер мне нужен, ибо это деталь реализации, которая может меняться по ходу работы. А полагаясь на понятие итератора можно улучшить масштабируемость системы.
Блин, я поражаюсь. А понятие сырой памяти является ещё более общим и, следовательно, (как ты утверждаешь) более высокоуровневым. Давайте всю стандартную библиотеку заточим под использование void*. Зачем мы создаём более удобные контейнеры, итераторы, свои классы для повторного использования? Зачем реализаторам стандартной библиотеки сопровождать все эти объекты?
Зачем существует boost::shared_ptr? Давайте с каждым указателем создавать переменную для подсчёта ссылок. И вручную её везде инкрементировать и декрементировать? А то ведь теперь же надо поддерживать boost::shared_ptr. Это ж сотня строк кода!
R>>2. Сокращение объёма кода, который необходимо писать и сопровождать. Ведь в подавляющем большинстве случаев алгоритмы выполняются именно для контейнеров, а не для последовательностей.
A>Ну не знаю... Сопровождать надо такой же объём кода: количество букв может быть и разное, но семантика же одна и та же... Даже наоборот, если для всех стандартных алгоритмов написать их версии для конкретных контейнеров, то придётся сопровождать несколько сотен совершенно ненужных функций... А то, что нужно больше печатать: лучше освоить слепой десяти-пальцевый метод набора и эта проблема больше не будет волоновать...
R>>3. Можно специализировать алгоритмы для контейнеров, которые не имеют итераторов, т.о. сохраняя единообразный синтаксис.
A>Что это за контейнеры, которые не имеют итераторов? Нахрен такие... Или обертки над ними сделать, с нормально определённым понятием итератора (я так и делаю).
Если имеется унаследованный контейнер с итераторами, но которые получаются функциями Start() и End(). Я не хочу каждый раз вспоминать имена этих функций, я опять же хочу просто выполнить алгоритм для этого контейнера.
Здравствуйте, srggal, Вы писали:
S>Здравствуйте, remark, Вы писали:
S>Я, в целом, не против "контейнерных" алгоритмов. S>Но я имею что сказать: S> Итераторы самодостаточны для алгоритмов, а именно, ИМХО использование итераторов делает алгоритмы более абстрактными, если так можно сказать.
S> Например, если бы не было интераторов и, соответсвенно, интервальных алгоритмов, а только "контейнерные", как бы выглядел следующий код на С++: S>
S>Соответсвенно возникает вопрос верно ли Ваше утверждение: S>
S>Вызов алгоритма через итераторы на начало и конец контерйнера — это более низкий уровень абстакции.
S>Ведь в приведенном мной примере — контейнера нет вообще, а интервальный алгоритм работать может, кроме того, он еще и правильно работает, и при этом — эот Стандартноне поведение, которое в очередной раз показывает "Не дураки стандарт писали"
Изначальная идея, что ничего не надо делать. Т.к. для контейнеров код всегда выглядит одинакого:
std::sort(v.begin(), v.end());
...
std::find(v.begin(), v.end(), ...);
...
std::sort(v.begin(), v.end());
...
std::find(v.begin(), v.end(), ...);
...
std::sort(v.begin(), v.end());
...
std::find(v.begin(), v.end(), ...);
...
И так везде.
А при использовании new, код всегда выглядит по разному:
std::sort(p, p + 100);
...
std::find(p, p + MAX_SIZE, ...);
...
std::sort(p, p + sizef(SomeStruct));
...
std::find(p, p2, ...);
И т.д.
Вывод: Если ты решаешь работать через new, то сам решай свой гемморой. Библиотека не будет вычислять размер твоего буфера.
А если ты используешь нормальный контейнер (std::vector), то будет тебе просто и удобно.
Здравствуйте, remark, Вы писали:
R>Ну вот уже в правильном направлении думаешь R>Представь себе винтик и автомобиль, что без чего может существовать и что является более высоким уровнем абстракции? R>Я не хочу каждый раз думать о каждом винтике, я хочу думать об автомобиле. Аналогично, когда я еду на автомобиле, я не хочу даже знать, что машина состоит из винтиков.
Уж если перейти на автомобильную тематику, то итераторы будут ближе к органам управления — "сцепление, тормоз, газ". Педали на всех авто (итераторы контейнеров) имеют одинаковый интрефейс — прямоугольная площадка . А уж какие они — механические, гидравлические, с ээлектронным ли приводом, вам как водителю не важно — сел и поехал.
Последовательности реализумые через итераторы легко позволяют работать с произвольными диапазонами и это большой плюс по сравнению с приделанными насильно к каждому контейнеру алгоритмами. Хотя я не отрицаю, что должны быть специализированные версии алгоритмов встроенные в контейнер, если они дают существенные преимущества по сравнению со стандартными.
Вообще насколько я понимаю, вам просто не нравится писать begin() и end(). Ну не пишите, сделайте обертки к каждому контейнеру кот. пользуетесь.
Вообще хочется услышать мнение по этому поводу местных гуру — Павла Кузнецова, Андрея Тарасевича, Кодта и др., не в обиду остальным участникам форума.
Ок, мысль понял, возможно что-то в этом есть, но на самом деле таки выходит
что и Вы считаете что работа с алгоритмами через прокси-какой либо является более высоким уровнем абстракции, чем использование алгоритмов, оперирующих контейнером ? -Именно об этом я говорил и пример привел по этой прчине
В этом то и проблема, что это более общее и низкоуровневое решение. Возможность работать с последовательностью естественно надо оставить, это я уже писал. Но в то же время надо дать более высокоуровневые и удобные средства работы.
И именно поэтому я и привел такой пример, мой ответ Я ответил здесь
Здравствуйте, srggal, Вы писали:
S>Ок, мысль понял, возможно что-то в этом есть, но на самом деле таки выходит S>что и Вы считаете что работа с алгоритмами через прокси-какой либо является более высоким уровнем абстракции, чем использование алгоритмов, оперирующих контейнером ? -Именно об этом я говорил и пример привел по этой прчине
Вижу, что этот спор плохой. Думаю сама фраза — "высокий/низкий уровен абстракции" несет в себе слишком много смыслов оттенков и т.п.
Скажу так: использовать iterator_range во многих местах (особенно при работе с последовательностями), выглядит логичнее и понятнее, чем просто с iterator и парой begin и end (например при сортировке). Хотя в других местах без просто итераторов не обойтись, например тот же OutputIterator. Если вы попробуете просто перевести все std алгоритмы на iterator_range, то столкнетесь с некоторыми проблемами, так как иногда без iterator не обойтись.
Возможно что базовым понятием нужно считать все таки iterator. Но это не значит что все алгоритмы в стандартной библиотеке должны использовать только базовые понятия и не использовать порожденные, так как, тогда и самим алгоритмам find, sort не место в стандартной библиотеке, про iostream вообще молчу точно не базовые понятие.
А вот про низкий и высокий уровень абстракции — это в философию программирования, там самые длинные топики.
Здравствуйте, sergey_shandar, Вы писали:
PC>>http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1871.html _>Этот полная копирка с Boost Range. Который еще содержит ошибки в коде и в дизайне. Например, почему нет доступа к ссылке на begin и end. Лично мне бы понравилось итерировать так:
Ну это пропозал от автора boost.range А для ошибок будет proposal Range Library Proposal (Revision 1)
_>
Пиши обертку и радуйся, но уже есть стандартный способ, и всё (надеюсь) будут пользовать именно его.
А еще (пример из C#) ???
while (c.MoveNext())
{
cout << c.Read();
}
_>Зачем const_begin, const_iterator и т.п.? Плодить монстров?
Абсолютно правильно, как без доступа read-only? Глянь кстати на boost.iterators — новый подход к итераторам.
Здравствуйте, sergey_shandar, Вы писали:
_>Здравствуйте, srggal, Вы писали:
_>>>
_>>>char *P = new char[PSize];
_>>>...
_>>>sort(make_range(P, P + PSize));
_>>>
S>>Я, как уже писал, не против идеи Рандж, S>>но в частном конкретном случае — этот код, Вы считаете лучше чем и эффективней чем:
S>>
S>>std::find( buf, buf + sizeof buf, '4' );
S>>
_>Нет, не считаю эффективнее.
Ок _>Но, считаю что обрабатывать контейнер, который сохранен в обычном указателе — плохой стлиь.
Не вижу ничего плохого, специально так и задумывалось умными людьми из комитета, да и не только из него.
Здравствуйте, srggal, Вы писали:
_>>Нет, не считаю эффективнее. S>Ок _>>Но, считаю что обрабатывать контейнер, который сохранен в обычном указателе — плохой стлиь. S> Не вижу ничего плохого, специально так и задумывалось умными людьми из комитета, да и не только из него.
Ладно, контрпример: представим что мы не только сортируем этот массив, а делаем еще кучу операций (как обычно), тогда я буду считать эффективным такой код:
Здравствуйте, srggal, Вы писали:
S>Здравствуйте, remark, Вы писали:
R>>Читай внимательнее первый пост
S>Вы писали про интервальные алгоритмы: S>
S>В этом то и проблема, что это более общее и низкоуровневое решение. Возможность работать с последовательностью естественно надо оставить, это я уже писал. Но в то же время надо дать более высокоуровневые и удобные средства работы.
S>И именно поэтому я и привел такой пример, мой ответ S>Я ответил здесь
Я имел в виду, что:
1. buf — контейнер из 6 байт, т.ч. контейнер тут есть. Если бы ничего не хранило объекты, то не к чему было бы и применять алгоритм.
2. Если программист хочет гемморой, используя голую память, то пусть сам и разбирается. Вычислять размер буфера по указателю библиотека не должна. Но не заставлять каждый раз писать "v.begin(), v.end()" она может.
Если сделать поиск по большому проекту на эту строку "*.begin(), *.end()", то в нём будет до фига таких мест. А с голой памятью всегда по разному вычисляется размер буфера.
Здравствуйте, Pavel Chikulaev, Вы писали:
_>>Зачем const_begin, const_iterator и т.п.? Плодить монстров? PC>Абсолютно правильно, как без доступа read-only? Глянь кстати на boost.iterators — новый подход к итераторам.
Этот "новый" подход давно видел. А read-only делаеться элементарно iterator<const Container>::type. А const_iterator бесполезная штука.
Ладно, контрпример: представим что мы не только сортируем этот массив, а делаем еще кучу операций (как обычно), тогда я буду считать эффективным такой код: _>
_>char *P = new char[PSize];
_>...
_>sort(P, P + PSize);
_>...
_>find(P, P +PSize, ...);
_>...
_>lexicographical_compare(P, P + PSize, PB, P + PBSize);
_>
Эффективным спорный вопрос, намного более читабельным — это да, это согласен.
А эффективномть в Вашем случае будет зависить от компилятора
_>К тому же вероятность появление багов в последнем — гораздо выше. Вот например в последней строке сидит багина, на глаз сразу не заметная.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, srggal, Вы писали:
S>>Здравствуйте, remark, Вы писали:
R>>>Читай внимательнее первый пост
S>>Вы писали про интервальные алгоритмы: S>>
S>>В этом то и проблема, что это более общее и низкоуровневое решение. Возможность работать с последовательностью естественно надо оставить, это я уже писал. Но в то же время надо дать более высокоуровневые и удобные средства работы.
S>>И именно поэтому я и привел такой пример, мой ответ S>>Я ответил здесь
R>Я имел в виду, что: R>1. buf — контейнер из 6 байт, т.ч. контейнер тут есть. Если бы ничего не хранило объекты, то не к чему было бы и применять алгоритм. R>2. Если программист хочет гемморой, используя голую память, то пусть сам и разбирается. Вычислять размер буфера по указателю библиотека не должна. Но не заставлять каждый раз писать "v.begin(), v.end()" она может. R>Если сделать поиск по большому проекту на эту строку "*.begin(), *.end()", то в нём будет до фига таких мест. А с голой памятью всегда по разному вычисляется размер буфера.
Ок, итераторы более абстрактны чем непосредственное использование в Алгоритмах, но при этом, я согласен, что реализация диапазонных и контейнерных алгоритмов — имею право на существование, но добавлю ИМХО чай тоже люблю с сахаром