可能:在具有相同键类型的不同映射上设置操作?

问题描述:

比方说,我有两个地图:可能:在具有相同键类型的不同映射上设置操作?

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()); 

我的实验结果意味着,有必要创建一个自定义插件,也许一个自定义键比较要做到这一点,但我想对于一些有识之士/快捷方式在做之前所以。

使用伊恩的意见,我的解决办法:

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()); 

我不认为这是可能的只使用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