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

时间:2010-03-23 22:46:03

标签: c++ stl map set

假设我有两张地图:

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

我的实验结果意味着有必要创建一个自定义插入器,也许还需要一个自定义键比较器来执行此操作,但在此之前我想要一些见解/快捷方式。

2 个答案:

答案 0 :(得分:1)

我不认为只使用没有自定义迭代器的stl就可以实现。您应该创建一个通用的select_1st_iterator。这会将任何迭代器包装成一对,并在取消引用时首先返回itr-&gt;。

注意:stl的一些扩展有一个select1st仿函数,它接受一对并返回第一个元素。但我还没有看到迭代器版本。

如果您打算编写迭代器,我建议您使用boost iterator libraryselect_1st_iterator最有可能的候选人是transfor_iterator

假设select_1st_iterator是一个创建真实select_1st_iterator_t类型的函数,它可能看起来像:

注意:如果您不使用resultSet 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()) );

,您的代码就会崩溃
{{1}}

答案 1 :(得分:1)

我的解决方案使用了iain的建议:

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