Мне трудно использовать std :: for_each и другие алгоритмы с мультикартой, и я хочу знать, может ли кто-нибудь помочь мне в разработке функтора, который мог бы передать соответствующий параметр "универсальным" функциям.
Моя конкретная проблема с map / multimap состоит в том, что их итераторы оценивают как std :: pair вместо содержащегося значения (я имею в виду mapped_type), с которым мне нужно работать. Итак, мой вопрос: есть ли способ передать правильное значение в функцию, предназначенную для работы с одним из содержащихся типов карт / мультикарт?
Вот мой пример кода:
// the key type for the multimap
typedef enum { ... } Module;
// my class as the mapped type for the multimap
struct Patch
{
void Apply(bool enable);
}
// I have some functors designed to work directly with Patch pointers
// because in other places I use set<Patch*> or other containers
struct ApplyOnCondtion: public unary_function<Patch*, void>
{
void operator() (Patch* patch)
{
if(some_condition) patch->Apply(enable_or_not);
}
}
// somewhere I have a collection of patches attributed to some module
multimap<Module, Patch*> patches;
// the problem is that using for_each with a map or a multimap results in
// a `pair<Module,Patch*>` as argument to the functor, not the Patch* as desired.
for_each(patches.begin(), patches.end(), ApplyOnCondition(...));
Я думаю, что, возможно, bind1st или bind2nd в сочетании с mem_fun могли бы решить эту проблему, или другой способ, который я могу придумать, - это создать новый функтор, который хранит оригинальный функтор и передает правильный член пары, но Мне не удается получить хороший результат. Может кто-нибудь с опытом работы в STL дать несколько советов?
EDIT 1
Хорошо, лучшее, что я могу получить, без использования boost или дополнительного временного контейнера, это:
#include <functional>
#include <utility>
using namespace std;
//////////////////////////////////////////////////////////////////////////
// any functor to be called must be derived from unary_function or
// have defined result_type and argument_type.
// template 'First' should be set to pair::first_type
template<typename First, typename Func>
class passSecond_t: public unary_function<
pair<First,typename Func::argument_type>,
typename Func::result_type>
{
Func* func;
public:
passSecond_t(Func &functor): func(&functor) {}
result_type operator()(argument_type value)
{
return (*func)(value.second);
}
};
// construction helper, unfortunately 'First' must be explicitly specified
template <typename First, typename Func>
passSecond_t<First, Func> passSecond(Func& functor)
{
return passSecond_t<First, Func> (functor);
}
// the following is a sample
#include <map>
#include <algorithm>
#include <iostream>
struct SampleClass
{
void execute(char* text)
{
cout << "this: " << this << ", text: " << text << endl;
}
};
struct SampleFunctor: public unary_function<SampleClass*,void>
{
char* text;
SampleFunctor(char* text_): text(text_) {}
result_type operator() (argument_type argu)
{
argu->execute(text);
}
};
void main()
{
map<int,SampleClass*> mymap;
SampleClass s1, s2;
mymap[0] = &s1;
mymap[1] = &s2;
SampleFunctor myfunctor("my text");
for_each(mymap.begin(), mymap.end(), passSecond<int>(myfunctor));
}