Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings)
Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует.
Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.
Главное гармония ...
Re: Сделать итератор из оператора []
От:
Аноним
Дата:
07.09.06 07:45
Оценка:
Здравствуйте, Mazay, Вы писали:
M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings) M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует. M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.
TStrings это базовый класс. В TStringList есть свойство Sorted.
А>TStrings это базовый класс. В TStringList есть свойство Sorted.
Спасибо за информацию. Но,к сожалению, в моём случае есть только указатель на TStrings. Можно конечно попробовать кастануть, но мне такой вариант не очень нравится.
Здравствуйте, Mazay, Вы писали:
M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings) M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует. M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.
Спасибо. То что надо. Но мне уже не поможет. Поскольку для использования этого шаблона я должен уметь делать так: node_base& dereference() const;
А я не могу вернуть ссылку на элемемнт контейнера . Могу только get(i)/set(i). Сейчас пытаюсь сочинить над этими аксессорами како-нибудь прокси. Но что-то всё печально получется. Такое чувство, что в плюсах этого в принципе не сделать
Mazay wrote:
> K>http://boost.org/libs/iterator/doc/iterator_facade.html#tutorial-example > > Спасибо. То что надо. Но мне уже не поможет. Поскольку для использования > этого шаблона я должен уметь делать так: node_base& dereference() const; > А я не могу вернуть ссылку на элемемнт контейнера . Могу только > get(i)/set(i). Сейчас пытаюсь сочинить над этими аксессорами како-нибудь > прокси. Но что-то всё печально получется. Такое чувство, что в плюсах > этого в принципе не сделать
А если этой node_base сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element&
operator(){return tstrings.get(i);}"?
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Mazay, Вы писали:
M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings) M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует. M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.
Если есть гарантия, что TString хранит строку в непрерывном блоке, то итераторы можно получить так:
TString str;
...
TChar* first = &str[0];
TChar* last = first + str.GetLength();
std::sort(first, last);
Здравствуйте, kan, Вы писали:
kan>Mazay wrote:
>> K>http://boost.org/libs/iterator/doc/iterator_facade.html#tutorial-example >> >> Спасибо. То что надо. Но мне уже не поможет. Поскольку для использования >> этого шаблона я должен уметь делать так: node_base& dereference() const; >> А я не могу вернуть ссылку на элемемнт контейнера . Могу только >> get(i)/set(i). Сейчас пытаюсь сочинить над этими аксессорами како-нибудь >> прокси. Но что-то всё печально получется. Такое чувство, что в плюсах >> этого в принципе не сделать kan>А если этой node_base сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element& kan>operator(){return tstrings.get(i);}"?
Пробовал. Только swap при таком раскладе на совсем правильно работает. Если при присваивании этих объектов (назовём их IterRef) делать копирование того на что они ссылаются (строк в TStrings tstrings), то при свопе одно значение теряется. Если при их присваивании копировать собственно ссылки (ну для данной "ссылки" копировать поля tstrings и i), то смысла в таком свопе очень мало. Получается что собственно строки не копируются. Конечно можно самому напистаь swap для таких "ссылок", но я думаю это не последняя функция где возникнут подобные проблеммы.
Mazay wrote:
> Пробовал. Только swap при таком раскладе на совсем правильно работает. > Если при присваивании этих объектов (назовём их IterRef) делать > копирование того на что они ссылаются (строк в TStrings tstrings), то > при свопе одно значение теряется. Если при их присваивании копировать
Э... почему теряются?.. Надо не копировать, а переставлять значения в TStrings, на которые ссылается IterRef
> собственно ссылки (ну для данной "ссылки" копировать поля tstrings и i), > то смысла в таком свопе очень мало. Получается что собственно строки не > копируются. Конечно можно самому напистаь swap для таких "ссылок", но я > думаю это не последняя функция где возникнут подобные проблеммы.
Дубовый способ — создать std::vector индексов (вектор длиной TStrings::Size, содержимое — числа
0..(TStrings::Size()-1)), отсортировать его (сравнивая индексируемые значения), потом переставить содержимое TStrings в
соответствие с этим вектором.
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, kan, Вы писали:
kan>Mazay wrote:
>> Пробовал. Только swap при таком раскладе на совсем правильно работает. >> Если при присваивании этих объектов (назовём их IterRef) делать >> копирование того на что они ссылаются (строк в TStrings tstrings), то >> при свопе одно значение теряется. Если при их присваивании копировать kan>Э... почему теряются?.. Надо не копировать, а переставлять значения в TStrings, на которые ссылается IterRef
А как переставлять? swap это делает через временную переменную и оператор присваивания. (tmp = a, a = b, b = tmp; )
>> собственно ссылки (ну для данной "ссылки" копировать поля tstrings и i), >> то смысла в таком свопе очень мало. Получается что собственно строки не >> копируются. Конечно можно самому напистаь swap для таких "ссылок", но я >> думаю это не последняя функция где возникнут подобные проблеммы.
kan>Дубовый способ — создать std::vector индексов (вектор длиной TStrings::Size, содержимое — числа kan>0..(TStrings::Size()-1)), отсортировать его (сравнивая индексируемые значения), потом переставить содержимое TStrings в kan>соответствие с этим вектором.
В крайнем случае я могу просто реализовать sort для TStrings. Весь огород затевался ради того чтоб бесшовно использовать TStrings с алгоритмами STL вообще. Похоже всё упирается в то, что из TStrings нельзя получить ссылку на его элемент. (Борладны — чёртовы велосипедисты. рррррр. Или это ещё один минус STL в копилку соседнего топика — почему я не могу отсортировать контейнер для которого просто определён operator[] ? Хотя в защиту STL надо заметить, что там не совсем честный оператор — это борландовое изобретение — property с индексом)
Здравствуйте, kan, Вы писали:
kan>А если ... сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element& kan>operator(){return tstrings.get(i);}"?
...то это не будет Random Access Iterator. Стандарт не позволяет итераторы со ссылками-прокси.
вовсе не приводит к изменению первого элемента strs. Зато приводит к AV. То что оказывается в указателе first указывает в никуда. А вот такой код срабатывает как и ожидается:
Здравствуйте, Roman Odaisky, Вы писали:
RO>Здравствуйте, kan, Вы писали:
kan>>А если ... сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element& kan>>operator(){return tstrings.get(i);}"?
RO>...то это не будет Random Access Iterator. Стандарт не позволяет итераторы со ссылками-прокси.
А вообще (если забыть про итераторы) существует ли какая-то разумная реализация такого прокси?
Mazay wrote:
>> > Пробовал. Только swap при таком раскладе на совсем правильно работает. >> > Если при присваивании этих объектов (назовём их IterRef) делать >> > копирование того на что они ссылаются (строк в TStrings tstrings), то >> > при свопе одно значение теряется. Если при их присваивании копировать > kan>Э... почему теряются?.. Надо не копировать, а переставлять значения > в TStrings, на которые ссылается IterRef > А как переставлять? swap это делает через временную переменную и > оператор присваивания. (tmp = a, a = b, b = tmp; )
IterRef можно сделать так, что если он никуда не зааттачен (создан пустым конструктором), то хранит данные внутри себя.
Тогда, вроде, такой своп заработает. Сам не пробовал, код набирал прямо тут.
>> > собственно ссылки (ну для данной "ссылки" копировать поля tstrings и i), >> > то смысла в таком свопе очень мало. Получается что собственно строки не >> > копируются. Конечно можно самому напистаь swap для таких "ссылок", но я >> > думаю это не последняя функция где возникнут подобные проблеммы. > > kan>Дубовый способ — создать std::vector индексов (вектор длиной > TStrings::Size, содержимое — числа > kan>0..(TStrings::Size()-1)), отсортировать его (сравнивая индексируемые > значения), потом переставить содержимое TStrings в > kan>соответствие с этим вектором. > В крайнем случае я могу просто реализовать sort для TStrings. Весь > огород затевался ради того чтоб бесшовно использовать TStrings с > алгоритмами STL вообще. Похоже всё упирается в то, что из TStrings > нельзя получить ссылку на его элемент. (Борладны — чёртовы > велосипедисты. рррррр. Или это ещё один минус STL в копилку соседнего > топика — почему я не могу отсортировать контейнер для которого просто > определён operator[] ? Хотя в защиту STL надо заметить, что там не
Потому что operator[] это по сути тоже самое, что и *iter, а значит у тебя были бы те же проблемы.
> совсем честный оператор — это борландовое изобретение — property с индексом)
Тогда это камень в огород багланда — ввели изобретение, а до ума не довели.
> Главное гармония ...
Эт-точно!
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Mazay, Вы писали:
...
Видимо, TStrings::operator[] возвращает AnsiString по значению В этом случае копирование должно быть достаточно эффективным, и, возможно, в качестве решения подойдет такой способ:
создаем vector AnsiString-ов из объекта TStrings
сортируем вектор с помощью std::sort
копируем вектор обратно.
Здравствуйте, Mazay, Вы писали:
kan>>>А если ... сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element& kan>>>operator(){return tstrings.get(i);}"?
RO>>...то это не будет Random Access Iterator. Стандарт не позволяет итераторы со ссылками-прокси.
M>А вообще (если забыть про итераторы) существует ли какая-то разумная реализация такого прокси?
Ну, если забыть про итераторы, то можно забыть и о std::sort. По поводу прокси — наверное, boost::reference_wrapper (aka Boost.Ref) может помочь.
Roman Odaisky wrote:
> kan>А если ... сделать объект, с операторами "operator=(const > Element&e){tstrings.set(i, e);}" и "Element& > kan>operator(){return tstrings.get(i);}"? > > ...то это не будет Random Access Iterator. Стандарт не позволяет > итераторы со ссылками-прокси.
Этот объект не итератор, а результат разыменования итератора.
Или я что-то не понял?
Posted via RSDN NNTP Server 2.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Mazay, Вы писали:
M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings) M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует. M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.
Что-то такое сваял
Конечно, заранее неизвестно, как отнесется мистический борландский компилятор (какой, кстати?) к коду, расположенному ниже, но на vc 7.1 на std::sort все работает достаточно стабильно:
Здравствуйте, Mazay, Вы писали:
M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings) M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует. M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.