Значить так.
Имеется абстрактный базовый класс.
class Foo
{
public:
// ...
virtual bar mf(int) = 0;
// ...
virtual void generator() = 0;
// ...
}
Потом создаётся много-много производных... и все они живут в
std::vector<Foo*> sequence;
Также имеетя некий manager, который делает с этим вектором много чего.
Хотелось бы выполнения функции в for_each(...) при каком-то условии. Написали for_each_if.
template <class InputIterator, class Predicate, class Function>
void for_each_if( InputIterator first, InputIterator last, Function f, Predicate pred )
{
while ( first != last ) {
if ( pred( *first ) )
f( *first++ );
else
first++;
}
}
Тааакс.. на чём мы значит остановились.. ааа даа... Понадобился мне, значить, предикат, чтобы делал проверку на range. Окей... тоже написали:
template <class T> class in_range
: public std::unary_function<T, bool>
{
T min;
T max;
public:
explicit in_range(const T& _min, const T& _max) : min(_min), max(_max) { }
bool operator()( const T& val ) const { return ( val >= min && val <= max); }
};
Значить, тапереча, если у нас будет
std::vector<int> seq;
то можна найти, допустим, первое число в диапазоне (min...max)
std::vector<int>::iterator res = find_if(seq.begin(),
seq.end(),
in_range<int>(min,max)
);
Есть и другая запись, собсна, того же действа,
std::vector<int>::iterator res = find_if(seq.begin(),
seq.end(),
compose2(logical_and<bool>(),
bind2nd(greater_equal<int>(), min),
bind2nd(less_equal<int>(), max)
)
);
но адаптер compose2 не является частью стандарта
так что остаётся 1ый вариант... на худой конец можно выдрать код из какого-нть SGI STL.
Значит в чём загвоздка. Хотелось бы на месте mim и max увидеть значения, возвращаемые Foo::mf(int).
Те что-то типа:
for_each_if(sequence.begin(), sequence.end(), mem_fun(&Foo::generator), in_range<bar>(Foo::mf(1), Foo::mf(2)));
// тока не бейте!! :)) это так... чтоб ход мыслей продемонстрировать...
На данный момент имеется несколько специализаций для in_range, заточенных под vector<Foo*>,
но если их число будет расти это не есть хорошо. Хотелось бы какого-нть более универсального подхода.
Жду советов и коментов!
... << RSDN@Home 1.1.3 beta 1 >>
Здравствуйте, lomezych, Вы писали:
L>Значить так.
Во первых, переделаем in_range:
template <class T>
bool in_range (const T& _min, const T& _max, const T& val )
{
return ( val >= _min && val <= _max);
}
Теперь при помощи буста твоя задача решаема:
for_each_if
(
sequence.begin(),
sequence.end(),
boost::mem_fn(&Foo::generator),
boost::bind
(
in_range<bar>,
boost::bind(&Foo::mf, _1, 1),
boost::bind(&Foo::mf, _1, 2),
10 // а для какого числа будем искать вхождение в диапазон? Я заменил его на 10
)
);
Правда, в задаче не понятно, какое число нужно передать в in_range для выяснения, входит ли оно в диапазон.
... << RSDN@Home 1.1.2 stable >>
Здравствуйте, ArtDenis, Вы писали:
AD>Во первых, переделаем in_range:
AD>AD>template <class T>
AD>bool in_range (const T& _min, const T& _max, const T& val )
AD>{
AD> return ( val >= _min && val <= _max);
AD>}
AD>
Было бы наверно лучше описать "in less<> terms". Хотя ладно... это не главное.
AD>Теперь при помощи буста твоя задача решаема:
AD>AD> for_each_if
AD> (
AD> sequence.begin(),
AD> sequence.end(),
AD> boost::mem_fn(&Foo::generator),
AD> boost::bind
AD> (
AD> in_range<bar>,
AD> boost::bind(&Foo::mf, _1, 1),
AD> boost::bind(&Foo::mf, _1, 2),
AD> 10 // а для какого числа будем искать вхождение в диапазон? Я заменил его на 10
AD> )
AD> );
AD>
AD>Правда, в задаче не понятно, какое число нужно передать в in_range для выяснения, входит ли оно в диапазон.
Да, блин, сорри... писал в попыхах... опечатался...На самом деле надо вот как:
min и мах — это как раз подставляемые значения.. а для выяснения, входит ли в диапазон — это как раз должно быть значение возвращаемое Foo::mf. Т.е. как я понял должно быть вот так:
for_each_if
(
sequence.begin(),
sequence.end(),
boost::mem_fn(&Foo::generator),
boost::bind
(
in_range<bar>,
min, // тут всё
max, // ясно
boost::bind(&Foo::mf, _1, value_passed_to_Foo_mf_function) // что собсна проверяем, входит ли в диапазон
)
);
Значит теперь усложним задачу. Получилось так, что надо предварительно надо перед сравнением переделать. Допустим есть функция (может быть как и член Foo, так и некая static).
baz barTobaz(bar);
Те меня интересует можно ли будет написать что-то вроде:
for_each_if
(
sequence.begin(),
sequence.end(),
boost::mem_fn(&Foo::generator),
boost::bind
(
in_range<baz>,
min_baz, // тут всё
max_baz, // ясно
boost::bind(
ptr_fn(barTobaz), // не уверен что в booste'е именно так
_1,
boost::bind(&Foo::mf, _1, value_passed_to_Foo_mf_function) // что собсна проверяем, входит ли в диапазон
)
)
);
С boost'ом я не очень знаком... Но решение конечно достаточно простое... Спасибо ArtDenis'у.
Но хотелось бы всё-таки уложиться в рамки стандарта STL.
Спасибо.... ждём-с ответа.
... << RSDN@Home 1.1.3 beta 1 >>
Здравствуйте, lomezych, Вы писали:
L>Да, блин, сорри... писал в попыхах... опечатался...На самом деле надо вот как:
L>min и мах — это как раз подставляемые значения.. а для выяснения, входит ли в диапазон — это как раз должно быть значение возвращаемое Foo::mf.
Тогда нужно оставить оригинальный in_range (как в самом первом посте)
L>Значит теперь усложним задачу. Получилось так, что надо предварительно надо перед сравнением переделать. Допустим есть функция (может быть как и член Foo, так и некая static).
Вот так:
for_each_if
(
sequence.begin(),
sequence.end(),
boost::mem_fn(&Foo::generator),
boost::bind
(
in_range<bar>(min, max),
boost::bind( Foo::barTobaz, boost::bind(&Foo::mf, _1, value_passed_to_Foo_mf_function) )
)
);
IMHO, три вложенных bind — это извращение. Лучше напиши
обычный цикл вместо for_each_if с
нормальными вызывами всех функций.
PS: сейчас кто-нибудь придёт и напишет тебе вариант с boost::lambda, но это будет ещё большим извращением.
... << RSDN@Home 1.1.2 stable >>