std::алгоритмы
От: Valus Россия  
Дата: 11.10.05 18:04
Оценка:
Алгоритмы из std используют интервалы итераторов, например
find(InputIterator _First, InputIterator _Last, const Type& _Val)

Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек
void gen_points(/*что тут писать?*/,int I);// I - число точек

Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь.
ЗЫЖ не сильно расплывчато спросил?
Re: std::алгоритмы
От: Tuo_Bellas Россия  
Дата: 11.10.05 18:32
Оценка: 1 (1)
Здравствуйте, Valus, Вы писали:

V>Алгоритмы из std используют интервалы итераторов, например

V>
V>find(InputIterator _First, InputIterator _Last, const Type& _Val)
V>

V>Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек
V>
V>void gen_points(/*что тут писать?*/,int I);// I - число точек
V>

V>Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь.
V>ЗЫЖ не сильно расплывчато спросил?

std::generate_n()?

HTH,
Tuo_Bellas.
Re: std::алгоритмы
От: Нахлобуч Великобритания https://hglabhq.com
Дата: 11.10.05 18:49
Оценка: 1 (1)
Здравствуйте, Valus, Вы писали:

V>Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек

V>
V>void gen_points(/*что тут писать?*/,int I);// I - число точек
V>

V>Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь.
V>ЗЫЖ не сильно расплывчато спросил?

Сильно Непонятно, что требуется. Что значит "как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь"? Параметр I разве не это указывает? А определение функции может выглядеть, например, так:

template <typename C>
void gen_points(C &container, size_t num)
{
    back_insert_iterator<C> i(back_inserter(container));
    for( ; num; --num, ++i)
    {
      *i = /* генерация точки */
    } // for
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Re[2]: std::алгоритмы
От: Valus Россия  
Дата: 11.10.05 19:14
Оценка:
Здравствуйте, Нахлобуч, Вы писали:

Н>Сильно Непонятно, что требуется. Что значит "как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь"? Параметр I разве не это указывает? А определение функции может выглядеть, например, так:


Н>
Н>template <typename C>
Н>void gen_points(C &container, size_t num)
Н>{
Н>    back_insert_iterator<C> i(back_inserter(container));
Н>    for( ; num; --num, ++i)
Н>    {
Н>      *i = /* генерация точки */
Н>    } // for
Н>}
Н>

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

и

б) а если мне надо не просто добавить в выходной контейнер, а после еще и поработать с ним (допустим сформировали vector с помощью back_insert_iterator, а затем работаем с этим вектором)
Re[2]: std::алгоритмы
От: Valus Россия  
Дата: 11.10.05 19:17
Оценка:
Здравствуйте, Tuo_Bellas, Вы писали:

T_B>std::generate_n()?

ЗАранее не известно сколько будет записано объектов в контейнер...
Re[3]: std::алгоритмы
От: Анатолий Широков СССР  
Дата: 11.10.05 19:29
Оценка:
Здравствуйте, Valus, Вы писали:

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


T_B>>std::generate_n()?

V>ЗАранее не известно сколько будет записано объектов в контейнер...

Как это не известно? "I — число точек"

>void gen_points(/*что тут писать?*/,int I);// I — число точек

Re[4]: std::алгоритмы
От: Valus Россия  
Дата: 11.10.05 19:50
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

АШ>

>>void gen_points(/*что тут писать?*/,int I);// I — число точек

ну... это какбы был пример, вопрос нне в том, что за алгоритм, а как добавить N штук в контейнер в процессе работы и не передавать ссылку на контейнер
Re[5]: std::алгоритмы
От: Кодт Россия  
Дата: 11.10.05 21:22
Оценка:
Здравствуйте, Valus, Вы писали:

V>Здравствуйте, Анатолий Широков, Вы писали:


АШ>>

>>>void gen_points(/*что тут писать?*/,int I);// I — число точек

V>ну... это какбы был пример, вопрос нне в том, что за алгоритм, а как добавить N штук в контейнер в процессе работы и не передавать ссылку на контейнер

1) Передавай итератор-адаптер, например, inserter или back_inserter.
2) Заранее сделай resize() контейнеру и передай итератор на первый неприсвоенный элемент
Перекуём баги на фичи!
Re[3]: std::алгоритмы
От: Кодт Россия  
Дата: 11.10.05 21:30
Оценка: 2 (1)
Здравствуйте, Valus, Вы писали:

V>а) не совсем это то... Неохото указывать тип контейнера в шаблоне, т.к. тогда и back_insert_iterator впринципе не к месту будет — напрямую проще.

V>нельзя по такой же схеме, как все std алгоритмы (без ссылок на контейнер)?

Можно.
// версия без явных ссылок на контейнер (естественно, back_inserter внутри знает, откуда ноги растут)
template<class OutputIterator>
void gen_points_it(OutputIterator it, int n)
{
  for(int i=0; i<n; ++i) // или for(; n>0; --n)
  {
    .....
    *it = xxxxxx;
    ++it;
  }
}

// версия, принимающая контейнер, а не инсертер
template<class Container>
void gen_points_cont(Container &cont, int n)
{
  gen_points_it(back_inserter(cont), n);
}


V>и


V>б) а если мне надо не просто добавить в выходной контейнер, а после еще и поработать с ним (допустим сформировали vector с помощью back_insert_iterator, а затем работаем с этим вектором)


Ну и работай на здоровье. Он же передан по ссылке.
vector<int> v(10);
gen_points_cont(v, 20);
gen_points_it(front_inserter(v), 5); // можно и с другого конца запихивать
cout << v.size(); // предположительно, 35
Перекуём баги на фичи!
Re[4]: std::алгоритмы
От: Valus Россия  
Дата: 12.10.05 09:28
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Можно.

К>
К>// версия без явных ссылок на контейнер (естественно, back_inserter внутри знает, откуда ноги растут)
К>template<class OutputIterator>
К>void gen_points_it(OutputIterator it, int n)
К>{
К>  for(int i=0; i<n; ++i) // или for(; n>0; --n)
К>  {
К>    .....
К>    *it = xxxxxx;
К>    ++it;
К>  }
К>}

К>// версия, принимающая контейнер, а не инсертер
К>template<class Container>
К>void gen_points_cont(Container &cont, int n)
К>{
К>  gen_points_it(back_inserter(cont), n);
К>}
К>

К>Ну и работай на здоровье. Он же передан по ссылке.
К>
К>vector<int> v(10);
К>gen_points_cont(v, 20);
К>gen_points_it(front_inserter(v), 5); // можно и с другого конца запихивать
К>cout << v.size(); // предположительно, 35
К>

в том то и дело, что придется заводить версию с передачей самого контейнера.
а вот так нельзя?
template<class EndIterator,class OutputIterator>
void some_alg(EndIterator eit,OutputIterator it)
{
  int i;
  EndIterator iter;
  for(i=0;i<1000;++i)
  {
    *it= bla-bla ;
    ++it;
  }
  eit=eit-i; //для random access к примеру
  /*делаем с элементами заполненного контейнера че хотим?*/
}
Re[5]: std::алгоритмы
От: Valus Россия  
Дата: 12.10.05 09:30
Оценка:
Здравствуйте, Valus, Вы писали:

V>Здравствуйте, Кодт, Вы писали:


К>>Можно.

К>>
К>>// версия без явных ссылок на контейнер (естественно, back_inserter внутри знает, откуда ноги растут)
К>>template<class OutputIterator>
К>>void gen_points_it(OutputIterator it, int n)
К>>{
К>>  for(int i=0; i<n; ++i) // или for(; n>0; --n)
К>>  {
К>>    .....
К>>    *it = xxxxxx;
К>>    ++it;
К>>  }
К>>}

К>>// версия, принимающая контейнер, а не инсертер
К>>template<class Container>
К>>void gen_points_cont(Container &cont, int n)
К>>{
К>>  gen_points_it(back_inserter(cont), n);
К>>}
К>>

К>>Ну и работай на здоровье. Он же передан по ссылке.
К>>
К>>vector<int> v(10);
К>>gen_points_cont(v, 20);
К>>gen_points_it(front_inserter(v), 5); // можно и с другого конца запихивать
К>>cout << v.size(); // предположительно, 35
К>>

V>в том то и дело, что придется заводить версию с передачей самого контейнера.
V>а вот так нельзя?
template<class EndIterator,class OutputIterator>
void some_alg(EndIterator eit,OutputIterator it)
{
  int i;
  EndIterator iter;
  for(i=0;i<1000;++i)
  {
    *it= bla-bla ;
    ++it;
  }
  iter=eit-i; //==begin() для random access к примеру
  /*делаем с элементами заполненного контейнера че хотим?*/
  while(iter!=eit)
  {
    *iter = bla-bla ;
  }
}
Re[6]: std::алгоритмы
От: Кодт Россия  
Дата: 12.10.05 10:36
Оценка: 1 (1)
Здравствуйте, Valus, Вы писали:

V>>в том то и дело, что придется заводить версию с передачей самого контейнера.

V>>а вот так нельзя?

С помощью эпической силы — всё можно.
Единственная засада, которую нам нужно обойти — это инвалидация итераторов контейнера после его изменения. Лечится путём введения прокси.
template<class Cont>
class lazy_iterator
{
  // ленивые данные
  Cont* cont;
  bool begin;
     // для итератора последовательного доступа есть 2 выделенных позиции: начало и конец;
     // для произвольного - можно указать смещение от начала или от конца (0 - начало, +n - от начала, -1 - конец, -n-1 - от конца)

  bool loaded;
  typename Cont::iterator it;

  void force()
  {
    if(loaded) return;
    it = begin ? cont->begin() : cont->end();
    loaded = true;
  }
public:
  lazy_iterator(Cont* c, bool b) : cont(c), begin(b), loaded(false) {}

  // далее, у всех операторов выполняем force
  typename Cont::iterator operator->() const { force(); return it; }
  typename Cont::reference_type operator*() const { force(); return *it; }
  lazy_iterator& operator++() const { force(); return it; }

  bool operator==(const lazy_iterator& rhs) const
  {
    if(!loaded && !rhs.loaded) return begin == rhs.begin;
    force(); rhs.force();
    return it == rhs.it;
  }
};
template<class Cont> lazy_iterator<Cont> lazy_begin(Cont& c) { return lazy_iterator<Cont>(c,true ); }
template<class Cont> lazy_iterator<Cont> lazy_end  (Cont& c) { return lazy_iterator<Cont>(c,false); }


.......
template<class Iter, class Inserter>
void your_function(Iter begin, Iter end, Inserter ins)
{
  // запихиваем через output iterator - Inserter
  for(int i=0; i<123; ++i) *ins++ = i;
  // обрабатываем через forward iterator'ы
  for_each(begin,end, do_something);
}
.......

your_function(lazy_begin(vec), lazy_end(vec), back_inserter(vec));

Это, разумеется, эскиз и большей частью изврат. Но если уж тебе так припёрло...
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.