2009-01-27 68 views
1

我很難在使用std :: for_each和其他算法的multimap,並想知道是否有人可以幫助我開發一個函數,可以傳遞適當的參數到「通用」函數。如何「調整」仿函數與map/multimap一起使用?

我的map/multimap的具體問題是它們的迭代器計算爲std :: pair而不是包含的值(我的意思是mapped_type),我需要使用它。所以,我的問題是,是否有一種方法可以將適當的值傳遞給設計用於包含map/multimap類型之一的函數?

這裏是我的示例代碼:

// 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或與mem_fun結合bind2nd可以解決這個問題,或者說我能想到的是其他的方式來創建一個新的仿函數,存儲原來的函子,並通過這對的正確成員,但我沒有設法得到任何好結果。任何有STL經驗的人都可以提供一些建議嗎?

EDIT 1 

好吧,我可以不使用升壓或額外的臨時容器最好是:

#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)); 
} 

回答

1

我在開始升壓解決方案:

for_each(patches.begin(), patches.end(), 
     boost::bind(ApplyOnCondition(...), 
        boost::bind(&map_type::value_type::second, _1))); 

這需要該對中的第二個成員,並將其推送到ApplyOnCondition的運算符()。 map_type是地圖的類型(當然是multimap<Module, Patch*>)。

1

可以使用std::transform抓住所有的值:

std::multimap<Module, Patch *> patches; 

std::vector<Patch *> values(patches.size()); 
std::transform(patches.begin(), patches.end(), values.begin(), 
    std::select2nd<std::multimap<Module, Patch *>::value_type>()); 

然後std::for_each對向量:

std::for_each(values.begin(), values.end(), ApplyOnCondition(...)); 
0

下面是其中的工作原理更像你會怎麼做這在功能性語言的解決方案:

/** 
    * Applies a function to the values in a map, producing a map with the same 
    * keys but containing the values produced by the function. 
    * In Haskell, the type of this function would be something like 
    * mapply :: (a -> b) -> Map c a -> Map c b 
    */ 
    template<typename Function, typename Key, typename InValue, typename OutValue> 
    static std::map<Key, OutValue> mapply(Function function, const std::map<Key, InValue>& inMap) { 
    typedef typename std::map<Key, InValue>::const_iterator InIterator; 
    const InIterator end(inMap.end()); 
    std::map<Key, OutValue> outMap; 
    for (InIterator i(inMap.begin()); i != end; ++i) { 
     outMap.insert(std::make_pair(i->first, function(i->second))); 
    } 
    return outMap; 
    } 

此代碼符合C++ 98標準。在C++ 11中,它可以被簡化。

另請注意,函數按值返回映射。沒關係,如果你沒有跡象表明它是你性能的瓶頸(過早優化是所有邪惡的根源),但是如果你有一個巨大的地圖,不要相信你的編譯器進行優化,你可能會更喜歡一個解決方案,其中「mapply」函數通過引用輸出一個輸出參數:一個填充鍵值對的映射。

相關問題