2010-03-23 87 views
2

比方說,我有兩個地圖:可能:在具有相同鍵類型的不同映射上設置操作?

typedef int Id; 
std::map<Id, std::string> idToStringMap; 
std::map<Id, double>  idToDoubleMap; 

而且我們說,我想這樣做對兩個地圖的按鍵設置操作。 有沒有比創建自定義「插入器」迭代器更簡單的方法?,這樣我可以這樣做:

std::set<Id> resultSet; 
set_difference(idToStringMap.begin(), idToStringMap.end(), 
       idToDoubleMap.begin(), idToDoubleMap.end(), resultSet.begin()); 

我的實驗結果意味着,有必要創建一個自定義插件,也許一個自定義鍵比較要做到這一點,但我想對於一些有識之士/快捷方式在做之前所以。

回答

1

使用伊恩的意見,我的解決辦法:

template <typename T> 
class Select1st 
: public std::unary_function<T&,typename T::first_type> 
{ 
    public: 
     int operator() (T & value) const 
     { 
      return value.first; 
     } 
}; 

template <typename T> 
class KeyGrabItorAdapter 
: public boost::transform_iterator< Select1st<typename T::value_type>, 
                typename T::iterator > 
{ 
    public: 
     KeyGrabItorAdapter(typename T::iterator itor) 
      : boost::transform_iterator<Select1st<typename T::value_type>, 
                 typename T::iterator> 
        (itor, Select1st<typename T::value_type>())   
     { 
     } 

}; 

具有前面允許以下內容:

typedef std::map<int, int> IntToIntMap; 
IntToIntMap intToIntMapA; 
IntToIntMap intToIntMapB; 

typedef std::map<int, double> IntToDoubleMap; 
IntToDoubleMap intToDoubleMapA; 
IntToDoubleMap intToDoubleMapB; 

KeyGrabItorAdapter<IntToIntMap> grabFirstABegin( intToIntMapA.begin()) ; 
KeyGrabItorAdapter<IntToIntMap> grabFirstAEnd(  intToIntMapA.end() ) ; 
KeyGrabItorAdapter<IntToDoubleMap> grabFirstBBegin(intToDoubleMapB.begin()) ; 
KeyGrabItorAdapter<IntToDoubleMap> grabFirstBEnd( intToDoubleMapB.end() ) ; 

std::set<int> intResultSet; 

set_difference(grabFirstABegin, grabFirstAEnd, 
       grabFirstBBegin, grabFirstBEnd, 
        inserter(intResultSet, intResultSet.begin()), 
         intToIntMapA.key_comp()); 
1

我不認爲這是可能的只使用stl沒有自定義迭代器。您應該創建一個通用的select_1st_iterator。這會將任何迭代器包裝爲一對,並在解除引用時返回itr-> first。

注意:stl的某些擴展名有一個select1st函子,它接受一對並返回第一個元素。但我沒有看到一個迭代器版本。

如果你打算寫一個迭代器,我建議你使用boost iterator library。對於select_1st_iterator最有可能的候選者是transfor_iterator

假設select_1st_iterator是創建真正的select_1st_iterator_t類型的函數,它可能看起來像:

注:您的代碼將崩潰,如果你不使用insert_iteratorresultSet

template<class T> 
select_1st_iterator_t<T> select_1st_iterator<T>(itr) 
{ 
    return select_1st_iterator_t<T>(itr); 
} 

std::set<Id> resultSet; 
set_difference(
    select_1st_iterator(idToStringMap.begin()), 
    select_1st_iterator(idToStringMap.end()), 
    select_1st_iterator(idToDoubleMap.begin()), 
    select_1st_iterator(idToDoubleMap.end()), 
    std::inserter(resultSet, resultSet.begin())); 
+0

謝謝!關於boost迭代器庫和transform_iterator提示的信息使我免於浪費精力。 :) – Catskul 2010-03-24 01:32:58

相關問題