Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек
void gen_points(/*что тут писать?*/,int I);// I - число точек
Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь.
ЗЫЖ не сильно расплывчато спросил?
V>Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек V>
V>void gen_points(/*что тут писать?*/,int I);// I - число точек
V>
V>Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь. V>ЗЫЖ не сильно расплывчато спросил?
Здравствуйте, Valus, Вы писали:
V>Как написать алгоритм в таком-же стиле, но чтобы была возможность самому устанавливать размер контейнера — например алгоритм формирования некого массива точек V>
V>void gen_points(/*что тут писать?*/,int I);// I - число точек
V>
V>Т.е. как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь. V>ЗЫЖ не сильно расплывчато спросил?
Сильно Непонятно, что требуется. Что значит "как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь"? Параметр I разве не это указывает? А определение функции может выглядеть, например, так:
Здравствуйте, Нахлобуч, Вы писали:
Н>Сильно Непонятно, что требуется. Что значит "как определить внутри алгоритма сколько точек записывать через выходной итератор в контейнер пользователь"? Параметр I разве не это указывает? А определение функции может выглядеть, например, так:
Н>
черт.. есть 2а момента.
а) не совсем это то... Неохото указывать тип контейнера в шаблоне, т.к. тогда и back_insert_iterator впринципе не к месту будет — напрямую проще.
нельзя по такой же схеме, как все std алгоритмы (без ссылок на контейнер)?
и
б) а если мне надо не просто добавить в выходной контейнер, а после еще и поработать с ним (допустим сформировали vector с помощью back_insert_iterator, а затем работаем с этим вектором)
Здравствуйте, Valus, Вы писали:
V>Здравствуйте, Tuo_Bellas, Вы писали:
T_B>>std::generate_n()? V>ЗАранее не известно сколько будет записано объектов в контейнер...
Как это не известно? "I — число точек"
>void gen_points(/*что тут писать?*/,int I);// I — число точек
Здравствуйте, Valus, Вы писали:
V>Здравствуйте, Анатолий Широков, Вы писали:
АШ>>
>>>void gen_points(/*что тут писать?*/,int I);// I — число точек
V>ну... это какбы был пример, вопрос нне в том, что за алгоритм, а как добавить N штук в контейнер в процессе работы и не передавать ссылку на контейнер
1) Передавай итератор-адаптер, например, inserter или back_inserter.
2) Заранее сделай resize() контейнеру и передай итератор на первый неприсвоенный элемент
Здравствуйте, 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
К>// версия без явных ссылок на контейнер (естественно, 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 к примеру
/*делаем с элементами заполненного контейнера че хотим?*/
}
Здравствуйте, 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 ;
}
}
Здравствуйте, 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) {}
// далее, у всех операторов выполняем forcetypename 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 - Inserterfor(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));
Это, разумеется, эскиз и большей частью изврат. Но если уж тебе так припёрло...