Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 07:33
Оценка:
Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский 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.
Re[2]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 07:56
Оценка:
Здравствуйте, Аноним, Вы писали:


А>TStrings это базовый класс. В TStringList есть свойство Sorted.


Спасибо за информацию. Но,к сожалению, в моём случае есть только указатель на TStrings. Можно конечно попробовать кастануть, но мне такой вариант не очень нравится.
Главное гармония ...
Re: Сделать итератор из оператора []
От: korzhik Россия  
Дата: 07.09.06 11:37
Оценка: 3 (1)
Здравствуйте, Mazay, Вы писали:

M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings)

M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует.
M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.

http://boost.org/libs/iterator/doc/iterator_facade.html#tutorial-example
Re[2]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 12:40
Оценка:
Здравствуйте, korzhik, Вы писали:

K>http://boost.org/libs/iterator/doc/iterator_facade.html#tutorial-example


Спасибо. То что надо. Но мне уже не поможет. Поскольку для использования этого шаблона я должен уметь делать так: node_base& dereference() const;
А я не могу вернуть ссылку на элемемнт контейнера . Могу только get(i)/set(i). Сейчас пытаюсь сочинить над этими аксессорами како-нибудь прокси. Но что-то всё печально получется. Такое чувство, что в плюсах этого в принципе не сделать
Главное гармония ...
Re[3]: Сделать итератор из оператора []
От: kan Великобритания  
Дата: 07.09.06 12:59
Оценка:
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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Сделать итератор из оператора []
От: Bell Россия  
Дата: 07.09.06 13:05
Оценка: +1
Здравствуйте, 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);
Любите книгу — источник знаний (с) М.Горький
Re[4]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 13:20
Оценка:
Здравствуйте, 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 для таких "ссылок", но я думаю это не последняя функция где возникнут подобные проблеммы.
Главное гармония ...
Re[5]: Сделать итератор из оператора []
От: kan Великобритания  
Дата: 07.09.06 13:44
Оценка:
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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 14:25
Оценка:
Здравствуйте, 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 с индексом)
Главное гармония ...
Re[4]: Сделать итератор из оператора []
От: Roman Odaisky Украина  
Дата: 07.09.06 14:35
Оценка:
Здравствуйте, kan, Вы писали:

kan>А если ... сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element&

kan>operator(){return tstrings.get(i);}"?

...то это не будет Random Access Iterator. Стандарт не позволяет итераторы со ссылками-прокси.
До последнего не верил в пирамиду Лебедева.
Re[2]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 14:38
Оценка:
Здравствуйте, Bell, Вы писали:


B>Если есть гарантия, что TString хранит строку в непрерывном блоке, то итераторы можно получить так:


B>
B>TString str;
B>...
B>TChar* first = &str[0];
B>TChar* last = first + str.GetLength();
B>std::sort(first, last);
B>


Всё гораздо хуже. Вот такой код:
TStrings strs;
...
AnsiString *first = &(strs->Strings[0]);
*first = "Hello!";  //щассс!


вовсе не приводит к изменению первого элемента strs. Зато приводит к AV. То что оказывается в указателе first указывает в никуда. А вот такой код срабатывает как и ожидается:

TStrings strs;
...
strs->Strings[0] = "Hello!";  //пишем
cout<<strs->Strings[0]; //читаем
Главное гармония ...
Re[5]: Сделать итератор из оператора []
От: Mazay Россия  
Дата: 07.09.06 14:43
Оценка:
Здравствуйте, Roman Odaisky, Вы писали:

RO>Здравствуйте, kan, Вы писали:


kan>>А если ... сделать объект, с операторами "operator=(const Element&e){tstrings.set(i, e);}" и "Element&

kan>>operator(){return tstrings.get(i);}"?

RO>...то это не будет Random Access Iterator. Стандарт не позволяет итераторы со ссылками-прокси.


А вообще (если забыть про итераторы) существует ли какая-то разумная реализация такого прокси?
Главное гармония ...
Re[7]: Сделать итератор из оператора []
От: kan Великобритания  
Дата: 07.09.06 14:50
Оценка: 2 (1)
Mazay wrote:

>> > Пробовал. Только swap при таком раскладе на совсем правильно работает.

>> > Если при присваивании этих объектов (назовём их IterRef) делать
>> > копирование того на что они ссылаются (строк в TStrings tstrings), то
>> > при свопе одно значение теряется. Если при их присваивании копировать
> kan>Э... почему теряются?.. Надо не копировать, а переставлять значения
> в TStrings, на которые ссылается IterRef
> А как переставлять? swap это делает через временную переменную и
> оператор присваивания. (tmp = a, a = b, b = tmp; )
IterRef можно сделать так, что если он никуда не зааттачен (создан пустым конструктором), то хранит данные внутри себя.

class IterRef
{
public:
  IterRef() : container_(NULL), index_(0){}
  IterRef(TStrings *container, size_t index) : container_(container), index_(index){}
  IterRef(const IterRef &src)
   : container_(NULL), index_(0)
  {
    *this = src;
  }
  void operator=(const IterRef &src)
  {
    *this = (TString &)src;
  }
  TString &operator()
  {
    return container_ ? container_.get(index_) : tmp_;
  }
  void operator=(const TString &val)
  {
    if(container_) container_.set(index, val);
    else tmp_ = val;
    return *this;
  }
private:
  TString tmp_;
  TStrings *container_;
  size_t index_;
};


Тогда, вроде, такой своп заработает. Сам не пробовал, код набирал прямо тут.

>> > собственно ссылки (ну для данной "ссылки" копировать поля 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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Сделать итератор из оператора []
От: Bell Россия  
Дата: 07.09.06 15:08
Оценка: 1 (1)
Здравствуйте, Mazay, Вы писали:
...
Видимо, TStrings::operator[] возвращает AnsiString по значению В этом случае копирование должно быть достаточно эффективным, и, возможно, в качестве решения подойдет такой способ:
создаем vector AnsiString-ов из объекта TStrings
сортируем вектор с помощью std::sort
копируем вектор обратно.
Любите книгу — источник знаний (с) М.Горький
Re[6]: Сделать итератор из оператора []
От: Roman Odaisky Украина  
Дата: 07.09.06 15:08
Оценка: 1 (1)
Здравствуйте, 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) может помочь.
До последнего не верил в пирамиду Лебедева.
Re[5]: Сделать итератор из оператора []
От: kan Великобритания  
Дата: 07.09.06 15:23
Оценка:
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
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Сделать итератор из оператора []
От: Ligen Украина http://zone-of-ambiguity.blogspot.com/
Дата: 08.09.06 19:44
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings)

M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует.
M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.

Что-то такое сваял
Конечно, заранее неизвестно, как отнесется мистический борландский компилятор (какой, кстати?) к коду, расположенному ниже, но на vc 7.1 на std::sort все работает достаточно стабильно:

Items processed: 100000
Garbage size: 190


// изврат, т.е. скорее proof-of-concept. 
// посему производительность, еще оставляет желать, 
// но можно еще оптимизить неограниченно

#include <vector>
#include <string>
#include <list>
#include <map>
#include <algorithm>
#include <memory>

// Нужный класс для теста, 
// Борланда под рукой нет
template<class ValueType>
class CIndexedOwner
{
    std::vector<ValueType> m_vec;
public:
    typedef ValueType value_type;

    CIndexedOwner(ValueType size)
        : m_vec(size)
    {
    }
    ValueType Get(int iIndex)
    {
        return m_vec[iIndex];
    }
    void Set(int iIndex, ValueType value)
    {
        m_vec[iIndex] = value;
    }

    template <class ContainerType>
    void GetStatistic(ContainerType * pContainer)
    {
        for(int i=0; i<(int)m_vec.size(); ++i)
            ++ (*pContainer)[ m_vec[i] ];
    }

};

// GARBAGE
struct IDestroyable
{
    virtual ~IDestroyable(){}
};

void DeleteSubject(IDestroyable * p)
{
    delete p;
}
class CHeapGarbage
{
    typedef std::list<IDestroyable * > ListType;
    ListType m_trash;
public:
    void Add(IDestroyable * pValue)
    {
        m_trash.push_back( pValue );
    }
    ~CHeapGarbage()
    {
        std::for_each(m_trash.begin(), m_trash.end(), &DeleteSubject);
    }
    int GetSize() const
    {
        return (int)m_trash.size();
    }
};

// эту сущность отдаем по ссылке - такой себе proxy
template<class OwnerType, class ValueType>
struct PseudoWrapper:public IDestroyable
{ 
    typedef PseudoWrapper<OwnerType, ValueType> SelfType;
    OwnerType * m_pOwner;
    int m_index;

    bool m_bStandaloneMode;
    ValueType m_value;
public:
    void SetValue(const ValueType & value)
    {
        if (m_bStandaloneMode) const
            m_value = value;
        else
            m_pOwner->Set( m_index, value );
    }

    ValueType GetValue() const
    {
        if (m_bStandaloneMode)
            return m_value;
        else
            return m_pOwner->Get(m_index);
    }

    // STANDALONE MODE
    PseudoWrapper()
        : m_bStandaloneMode(true)
    {
    }

    PseudoWrapper(const SelfType & value)
        : 
           m_bStandaloneMode(true),
          m_value( value.GetValue() )
    {
    }
    
    PseudoWrapper(const ValueType & val)
        : m_bStandaloneMode(true),
          m_value(val)
    {
    }

    // PROXY MODE
    PseudoWrapper(OwnerType * pOwner, int index)
        : m_pOwner( pOwner ),
          m_index( index ),
          m_bStandaloneMode(false)
    {
    }

    // ALL MODES
    bool operator == (const SelfType & value)const
    {
        return GetValue() == value.GetValue();
    }
    bool operator < (const SelfType & value)const
    {
        return GetValue() < value.GetValue();
    }
    SelfType & operator = (const SelfType & value)
    {
        SetValue( value.GetValue() );
        return *this;
    }
    operator ValueType () const
    {
        return GetValue();
    }
    bool operator == (const ValueType & value)const
    {
        return GetValue() == value;
    }
    bool operator < (const ValueType & value)const
    {
        return GetValue() < value;
    }
    SelfType & operator = (const ValueType & value)
    {
        SetValue( value );
        return *this;
    }

};

// cache
template<class ObjectType>
class CRefCache
{
public:
    typedef std::map<void *, ObjectType *> Cache;
    typedef typename Cache::iterator iterator;

    std::pair<iterator, bool> insert(void * pAddress)
    {
        return m_cache.insert( std::pair<void *, ObjectType *>(pAddress, 0) );
    }

private:
    Cache m_cache;

};

// Наша цель:
template<class OwnerType, class ValueType, class RefCacheType>
class WeakRandomIterator
{
    typedef WeakRandomIterator<OwnerType, ValueType, RefCacheType> SelfType;
    OwnerType * m_pOwner;
    CHeapGarbage * m_pGarbage;
    int m_index;
    mutable RefCacheType * m_pCache;

public:
    typedef typename std::random_access_iterator_tag iterator_category;
    typedef ValueType value_type;
    typedef int difference_type;
    typedef difference_type distance_type;    // retained
    typedef ValueType * pointer;
    typedef ValueType & reference;

    typedef PseudoWrapper<OwnerType, ValueType> UsedWrapper;

    WeakRandomIterator()
    {
        m_pOwner = 0;
        m_pGarbage = 0;
        m_index = 0;
        m_pCache = 0;
    }

    SelfType & operator = (const SelfType & other) 
    {
        m_pOwner = other.m_pOwner;
        m_pGarbage = other.m_pGarbage;
        m_index = other.m_index;
        m_pCache =  other.m_pCache;
        return *this;
    }

    WeakRandomIterator(OwnerType * pOwner, 
                       CHeapGarbage * pGarbage,
                       int index,
                       RefCacheType * pCache)
    : 
                m_pOwner( pOwner ),
                m_pGarbage( pGarbage ),
                m_index( index ),
                m_pCache( pCache )
    {
    }

    // interesting situation below:
    UsedWrapper & operator * () 
    {
        return GetReference();
    }

    const UsedWrapper & operator * () const 
    {
        return GetReference();
    }

    UsedWrapper & GetReference()
    {
        std::pair<typename RefCacheType::iterator, bool> res = 
            m_pCache->insert( this );

        UsedWrapper * pNewObject = 0; 
        if (res.second)
        {
            // need's update
            std::auto_ptr<UsedWrapper> ptr( new UsedWrapper( m_pOwner, m_index ) );
            res.first->second = ptr.get();
            m_pGarbage->Add( ptr.get() );
            pNewObject = ptr.release();
        } 
        else
        {   // take existing
            pNewObject = &(*res.first->second);
            pNewObject->m_index = m_index;
            pNewObject->m_pOwner = m_pOwner;
        }
        return *pNewObject;
    }
    
    // операции, необходимые для std::sort
    int operator - (const SelfType & iterator) const 
    {
        return m_index - iterator.m_index;
    }

    SelfType operator - (int size) const 
    {
        return SelfType(m_pOwner, m_pGarbage, m_index - size, m_pCache);
    }

    SelfType operator + (int size) const 
    {
        return SelfType(m_pOwner, m_pGarbage, m_index + size, m_pCache);
    }
    
    bool operator < (const SelfType & obj) const 
    {
        return m_index<obj.m_index;
    }

    SelfType & operator ++ ()  
    {
        ++m_index;
        return *this;
    }

    SelfType operator ++ (int)  
    {
        SelfType obj = *this;
        ++m_index;
        return obj;
    }

    SelfType & operator -- ()  
    {
        --m_index;
        return *this;
    }

    SelfType operator -- (int) 
    {
        SelfType obj = *this;
        --m_index;
        return obj;
    }

    bool operator == (const SelfType & other) const 
    {
        return other.m_index == m_index;
    }
    
    bool operator != (const SelfType & other) const 
    {
        return other.m_index != m_index;
    }
    // foo
    ValueType Get()
    {
        return m_pOwner->Get(m_index);
    }
    void Set(const ValueType & str)
    {
        m_pOwner->Set(m_index, str);
    }

};

// for test
#include <iostream>
#include <stdlib.h>
#include <time.h>

typedef CIndexedOwner<int> CTestOwner;

int main()
{
    srand( (unsigned)time( 0 ) );

    // DATA:
    int containerSize = 10000;
    CTestOwner owner( containerSize ); 
    for(int i=0; i<containerSize; ++i)
        owner.Set(i, rand());

    // type declarations
    typedef int ValueType;
    typedef CTestOwner OwnerType;
    typedef CRefCache< PseudoWrapper<OwnerType, ValueType> > CUsedCache;
    typedef WeakRandomIterator<OwnerType, ValueType, CUsedCache> CUsedIterator;


    // пример использования
    CHeapGarbage garbage;
    CUsedCache cache;

    std::map<CTestOwner::value_type, int> statBefore, statAfter;

    owner.GetStatistic( &statBefore );
    std::sort(  CUsedIterator(&owner, &garbage, 0, &cache), 
                CUsedIterator(&owner, &garbage, containerSize, &cache));
    owner.GetStatistic( &statAfter );

    // проверим корректность
    if (statAfter != statBefore)
    {
        std::cout<<"Statistic test failed\n";
        return 1;
    }


    for(int i=1; i<containerSize ;++i)
    {
        if (owner.Get(i-1) > owner.Get(i))
        {
            std::cout<<"Test failed on position:  "<<i<<"\n";
            return 2;
        }
    }

    std::cout<<"Items processed:  "<<containerSize<<"\n";
    std::cout<<"Garbage size:  "<<garbage.GetSize()<<"\n";
    return 0;
}


M>Главное гармония ...

Viva el Junta Militar! Viva el Presidente!
Re: Сделать итератор из оператора []
От: korzhik Россия  
Дата: 08.09.06 20:32
Оценка:
Здравствуйте, Mazay, Вы писали:

M>Понадобилось отсортировать контейнер, в котором доступ к элементам осуществляется по индексу. (Борладновский TStrings)

M>Взялся было за std::sort(), но быстро понял, что RandomAccessIterator'ов у меня нету. В принципе написать адаптер не сложно, но есть подозрение что не я первый и такой велосипед уже существует.
M>Если у вас есть такой адаптер/обёртка — поделитесь пожалуйста. Можно ткнуть носом в какой-нить boost::* или std::*.


возьми это:
http://vector-agg.cvs.sourceforge.net/vector-agg/agg-2.4/include/agg_array.h?revision=1.11&amp;view=markup

начиная с линии 900 quick sort, требует только operator[]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.