с какой стороны подойти, не пойму...
есть иерархия классов, все имеющие свою версию MyClass::run(); есть вектор std::vector<MyClass*> pClasses;
в какой-то момент времени нужно все их пробежать, т.е. отрабатывает for_each(pClasses.begin(), pClasses.end(), Execute()); где
но фишка в том, что на определенном шаге энному члену нужно иметь возможность каким-то образом прекратить все дальнейшие "запуски" MyClass::run() у оставшейся цепочки, т.е. какбы сэмулировать завершение вышеуказанного for_each(...);
есть идеи? был бы признателен.
Здравствуйте, Vamp, Вы писали:
А>>есть идеи? был бы признателен. V>Исключение?
вариант!
я только что тоже придумал вариант -- с хранением ссылки "MyClass &parent" на "родительский"/"вышестоящий" MyClass, которую мы будем помещать в каждый MyClass. а в функтор выше добавляем условие "_Parent->stillRunning() == true". но такой подход мне не нравится — если будет большая вложенность объектов др в друга, будут десятки холостых таких проверок.
вариант с исключениями, думаю, подходит лучше!
Здравствуйте, Аноним, Вы писали:
А>с какой стороны подойти, не пойму... А>есть иерархия классов, все имеющие свою версию MyClass::run(); есть вектор std::vector<MyClass*> pClasses; А>в какой-то момент времени нужно все их пробежать, т.е. отрабатывает for_each(pClasses.begin(), pClasses.end(), Execute()); где А>
А>но фишка в том, что на определенном шаге энному члену нужно иметь возможность каким-то образом прекратить все дальнейшие "запуски" MyClass::run() у оставшейся цепочки, т.е. какбы сэмулировать завершение вышеуказанного for_each(...); А>есть идеи? был бы признателен.
Run/Execute возвращает true если надо прервать цепочку, иначе false.
Потом вместо for_each вызываем find_if.
Или я чего-то не понимаю?
Re[2]: прервать цепочки вызовов, как??
От:
Аноним
Дата:
11.07.08 16:18
Оценка:
Здравствуйте, Pretender, Вы писали:
хмм, распиши плз поподробнее. особливо недопонял я про find_if.
Здравствуйте, Аноним, Вы писали:
А>с какой стороны подойти, не пойму... А>есть иерархия классов, все имеющие свою версию MyClass::run(); есть вектор std::vector<MyClass*> pClasses; А>в какой-то момент времени нужно все их пробежать, т.е. отрабатывает for_each(pClasses.begin(), pClasses.end(), Execute()); где А>
А>но фишка в том, что на определенном шаге энному члену нужно иметь возможность каким-то образом прекратить все дальнейшие "запуски" MyClass::run() у оставшейся цепочки, т.е. какбы сэмулировать завершение вышеуказанного for_each(...); А>есть идеи? был бы признателен.
скажите...а почему вы пишете for_each, обьявляя читателю, что вы заказываете некую обработку КАЖДОГО элемента вектора, а потом заявляете, что каждый элемент вектора вам обрабатывать и не нужно?
может в консерватории чего не так???
или вы считаете что дословный перевод for_each тут неуместен?
Здравствуйте, merk, Вы писали:
M>скажите...а почему вы пишете for_each, обьявляя читателю, что вы заказываете некую обработку КАЖДОГО элемента вектора, а потом заявляете, что каждый элемент вектора вам обрабатывать и не нужно? M>может в консерватории чего не так??? M>или вы считаете что дословный перевод for_each тут неуместен?
в первом посте я вроде бы внятно описал суть проблемы -- пробегаться по элементам вектора и вызывать ф-цию-член run() последовательно для каждого элемента до тех пор, пока определенное условие не станет истинным. согласен, for_each ненаглядно для описания, но как бы я мог иначе описать суть вопроса?
вся фишка в том, что нек. MyClass* могут являться указателями на MyClassList, т.е. что-то типа:
class MyClass{
public:
//...virtual void run(){
//какие-то действия
}
};
class Execute{
public:
operator()(const MyClass *p){
p->run();
}
};
class MyClassList : public MyClass{
std::vector<MyClass *> _list;
public:
//...void run(){
std::for_each(_list.begin(); _list.end(); Execute()); отрабатывает целый список
}
};
std::vector<MyClass *> entries;
//заполнили
//здесь необходимо пробежаться по entries и для кажд его элемента запустить его ф-цию-член run(), НО по достижении определенного условия, которое может произойти при вызове текущей run() для текущегшо указателя прекратить полностью ВСЕ дальнейшие переборы (в том числе и вложенные).
пардон, если я сразу не понятно все описал.
Re[4]: прервать цепочки вызовов, как??
От:
Аноним
Дата:
11.07.08 16:55
Оценка:
Здравствуйте, ilnar, Вы писали:
I>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, Pretender, Вы писали:
А>>хмм, распиши плз поподробнее. особливо недопонял я про find_if.
Здравствуйте, Pretender, Вы писали:
P>Run/Execute возвращает true если надо прервать цепочку, иначе false.
P>Потом вместо for_each вызываем find_if.
P>Или я чего-то не понимаю?
Имя find_if несёт семантику поиска. Как правило, поиск не даёт побочных эффектов. В то время как метод run без параметров явно вызывается ради побочных эффектов.
Думаю, семантически правильно было бы написать отдельный алгоритм с отдельным именем (скажем, for_each_while или for_each_until), пусть даже и реализованный как обёртка над find_if.
Здравствуйте, Аноним, Вы писали:
А>с какой стороны подойти, не пойму... А>есть иерархия классов, все имеющие свою версию MyClass::run(); есть вектор std::vector<MyClass*> pClasses; А>в какой-то момент времени нужно все их пробежать, т.е. отрабатывает for_each(pClasses.begin(), pClasses.end(), Execute()); где
Ох уж эти космонавты, им звезды звезды, а у нас в селе все просто делается.
Здравствуйте, Pretender, Вы писали:
P>Run/Execute возвращает true если надо прервать цепочку, иначе false.
В это случае не понятна будет причина прерывания. Исключение более информативно.
Здравствуйте, techgl, Вы писали:
T>Здравствуйте, Pretender, Вы писали:
P>>Run/Execute возвращает true если надо прервать цепочку, иначе false. T>В это случае не понятна будет причина прерывания. Исключение более информативно.
1. Зато более затратно.
2. Программа должна поддерживать безопастность исключений.
3. Да и не для того они были придуманы.
4. В задаче не сказано что нам важно знать причину почему надо прервать выполнение. Плюс дошли или нет до конца можем узнать по результату find_if.
Здравствуйте, Centaur, Вы писали:
C>Имя find_if несёт семантику поиска. Как правило, поиск не даёт побочных эффектов. В то время как метод run без параметров явно вызывается ради побочных эффектов.
усть даже и реализованный как обёртка над find_if.
Согласен. Но семантика for_each ещё сильней нарушена.
offtop: Нехватает алгоритмов and(iterator, iterator, bool(value))/or(...) работающих до первого false/true
Здравствуйте, Pretender, Вы писали:
P>1. Зато более затратно.
Это самое узкое место программы? В исходной задаче, опять же, ничего не написано о требованиях, чтобы оценивать что затратно.
P>3. Да и не для того они были придуманы.
В методе run что-то пошло не так, это исключительная ситуация, которая к тому же, прекращает всю дальнейшую цепочку. Вполне опревдано тут исключение.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: прервать цепочки вызовов, как??
От:
Аноним
Дата:
13.07.08 10:52
Оценка:
сейчас все пересмотрел, и решил остановиться на простом цикле, предложенным выше уважаемым IROV...
думаю, это верное решение, т.к. не надо усложнять сверх необходимого, и все должно быть прозрачно для понимания. а исключение -- в любом случае явл. накладными расходами.
всем спасибо еще раз за пояснения.
Здравствуйте, techgl, Вы писали:
P>>3. Да и не для того они были придуманы. T>В методе run что-то пошло не так, это исключительная ситуация, которая к тому же, прекращает всю дальнейшую цепочку. Вполне опревдано тут исключение.
Этого автор не сказал. Если прерывание является штатной ситуацией, то надо юзать простой цикл. find_if же обфускирует семантику происходящего.
Здравствуйте, IROV.., Вы писали:
IRO>Здравствуйте, Аноним, Вы писали:
А>>с какой стороны подойти, не пойму... А>>есть иерархия классов, все имеющие свою версию MyClass::run(); есть вектор std::vector<MyClass*> pClasses; А>>в какой-то момент времени нужно все их пробежать, т.е. отрабатывает for_each(pClasses.begin(), pClasses.end(), Execute()); где
IRO>Ох уж эти космонавты, им звезды звезды, а у нас в селе все просто делается.
Не космонавты, а эстеты.
Нам что-нить вроде do_until или for_each_until подавай. Хотя это же можно за пять минут на коленке сляпать
Здравствуйте, landerhigh, Вы писали:
L>Не космонавты, а эстеты.
L>Нам что-нить вроде do_until или for_each_until подавай. Хотя это же можно за пять минут на коленке сляпать
Иногда эти вещи прячутся от таких эстетов.
# include <stdio.h>
# include <vector>
# include <algorithm>
class MyClass
{
public:
explicit MyClass( bool _until )
: m_until(_until)
{
}
public:
bool update() const
{
printf("1\n");
return m_until;
}
protected:
bool m_until;
};
int main()
{
std::vector<MyClass *> v;
v.push_back( new MyClass( false ) );
v.push_back( new MyClass( false ) );
v.push_back( new MyClass( false ) );
v.push_back( new MyClass( true ) );
v.push_back( new MyClass( false ) );
struct UpdateUntil
{
bool operator () ( MyClass * _my )
{
return _my->update();
}
};
std::find_if( v.begin(), v.end(), UpdateUntil() );
}