可能:在具有相同键类型的不同映射上设置操作?
问题描述:
比方说,我有两个地图:可能:在具有相同键类型的不同映射上设置操作?
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_iterator
为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()));
谢谢!关于boost迭代器库和transform_iterator提示的信息使我免于浪费精力。 :) – Catskul 2010-03-24 01:32:58