LINUX.ORG.RU

foreach с предоставлением информации об элементах?

 , ,


0

1

Сабж. Вот есть у меня какой то хитрый контейнер и в нем есть итератор и все что положено. Я могу делать обычный цикл

for(auto I=arr.begin(); I!=arr.end(); ++I){ ... }
и внутри этого цикла знать не только сам элемент но и доп. информацию (позиция в контейнере и всяко разно - все что итератор может рассказать).

Могу сделать foreach

for(T& x:arr){ ... }
и тут я буду знать только значения элемента.

Но я могу ведь сделать такую штуку

class Arr{
...
   struct Cell{ 
      T& operator *(){...}
      T* operator ->(){...}
      ... // всякие методы рассказывающие об элементе контейнера
   };
   struct iterator: public Cell{ 
       Cell& operator *(){ return *this; }
       ... 
   };
};
и тогда
for(auto& x:arr){ ... }
мне позволит получить доступ не только к элементу но и к информации об элементе.

Из бонусов - меньше букв писать при организации цикла. Из плохого - это как то наверное не очевидно для пользователя?

Вопрос - насколько это вообще плохое решение и почему.


как то наверное не очевидно для пользователя

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

Вопрос - насколько это вообще плохое решение и почему.

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

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

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

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

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

Хочется еще конечно параллельный итератор с поддержкой OpenMP, но там скорее идеологические сложности.

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

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

anonymous ()

Вопрос - насколько это вообще плохое решение и почему.

для вас это плохое решение, потому-что очевидно у вас потребности в нём нет, просто что-то где-то свербит :-)

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

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

А какая функциональность лежит на итераторе кроме обхода и возврата ключа?

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

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

а тогда что-то вы тут обсуждаете ?

раз (острая!!)потребность у вас с коллегами то и объективные оценки только от них. У вас внутри коллектива сразу заказчик+разработчик+тестер. А ЛОР он ни разу ни в чём внешний эксперт.

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

Ни я ни коллеги не являемся программистами (настоящими тык-скыть).

Так что тут как раз интересно мнение настоящих программистов с ЛОР-а, обычно они очень активно критикуют чужой дизайн;-)

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

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

Т.е. это нестандратная задача (обычно она не возникает), и каждый ее решает в меру своей упоротости, стандартных решений нет? Я правильно понял?

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

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

Тут была тема с определением из базового класса характеристик дочернего или что то вроде этого - это было извращение, а у вас вполне адекватное и рабочее решение.

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

Ок, спасибо. А как правильно называют такой недоитератор (который не умеет переходить к след. элементу но может рассказать много всего о текущем элементе + дает доступ к соседям)?

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

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

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

Ок;-) У меня это Cell (поскольку речь идет о расчетной сетке и это информация о ячейке). Видимо будет еще Face (для граней ячейки) и еще всякие - мне понравилась такая технология в работе, очень компактный код выходит.

Да, наверное проблемно-ориентированные названия тут более Ъ.

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

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

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

Ок. А насколько плохо то, что у меня в итераторах операция != перегружена только в контексте выхода из цикла (де-факто проверяется флаг окончания прохода или что то в этом роде)?

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

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

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

anonymous ()

foreach - это синтаксический сахар, который разворчивается в цикл (псевдокод)

for(it = begin(); it != end(); ++it) { x = *it; ... }

Надо реализовать begin(), end(), сравние с end() (именно с концом), инкремент ++, и доступ *. Во всем остальном - полная свобода.

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

Еще неплохо иметь ->

Это твоя свобода - можешь иметь, можешь не иметь.

И сравнение именно с концом не обязательно, можно просто по != возвращать false для выхода из цикла.

Главное, чтобы имело смысл выражение it != end(). Сам end() может, например, возвращать объект-пустышку struct ... {}, для которго перегружен оператор сравнения.

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

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

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

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

Этих недостатков напрочь лишены ranges, but в плюсах уже третью версию их реализовали, а народ ими не пользуется так как реализация подкачала. В D ranges используются везде много лет и они очень эффективны, естественны и удобны.

З.Ы. Но итераторы более мощная штука чем ranges и иногда без них не обойтись, т.е. они не взаимоисключающие.

anonymous ()