我有一个特定的搜索功能。因为它在std::set
和std::map
上使用,所以它在我们的代码中重复(不使用模板)。
我必须维护这两个函数,并且我想使用模板将它们移动到单个函数(然后只有一个搜索预处理要维护)。
我找不到如何将迭代器转换为容器的value_type
。对于std::set
,您只需要取消引用迭代器(* iter),但是对于std::map
,您需要访问迭代器的第二项(这是一对)iter->second
。< / p>
这是一个孤立的例子:
template <class Container, class Object> bool MyFindFunction( const Container& container, Object& found )
{
Container::const_iterator iter = container.begin();
// do my special search procedure here
// note that this code also needs to access the iterator's value...
if ( iter != container.end() )
{
found = *iter; // this works for set, but not for map
found = iter->second; // this works for map, but not for set
// HOW TO MAKE IT WORK FOR BOTH??
return true;
}
else
{
return false;
}
}
int main ()
{
std::set<double> mySet;
std::map<int,double> myMap;
double found = 0;
MyFindFunction( mySet, found );
MyFindFunction( myMap, found );
}
请注意,特殊搜索过程还需要访问value_type
(或地图的mapped_type
),因此,将此过程移至模板函数并具有MyFindFunctionInMap
和{{在调用搜索过程函数后,函数处理迭代器到值转换将无济于事。
PS:对不起,我正在使用C ++ 98 ..
答案 0 :(得分:3)
您可以使用template function overload
来区分这些情况:
template <typename V>
inline V get_value(const V& v) { return v; }
template <typename K, typename V>
inline V get_value(const std::pair<K, V>& p) { return p.second; }
然后
found = get_value(*iter);
答案 1 :(得分:1)
你可以使用boost::transform_iterator
来构建一个set
- 就像map
那样的迭代器 - 就像迭代器一样。
创建一个由set
参数化的内部模板函数 - 就像迭代器一样,只将迭代器而不是容器作为参数。将此函数调度为原始迭代器或转换后的迭代器。
编辑如果你不能使用boost,请构建一些函子来访问你的东西:
#include <map>
#include <set>
#include <iostream>
using namespace std;
template<class Key, class Value>
struct access_key
{
template<class Ref>
const Key &operator()(const Ref &v) const
{
return v.first;
}
};
template<class Key>
struct access_key<Key, Key>
{
template<class Ref>
const Key &operator()(const Ref &v) const
{
return v;
}
};
template<class Container>
void fn(Container t)
{
access_key<typename Container::key_type, typename Container::value_type> a;
cout << a(*t.begin()) << endl;
}
int main()
{
set<int> s;
s.insert(1);
map<int, int> m;
m[1] = 1;
fn(s);
fn(m);
return 0;
}
此访问器依赖于键/类型和值类型对于map / set是不同的/相同的。
答案 2 :(得分:-1)
一个实用的解决方案是使用额外的布尔参数来确定容器是否为map:
template <class Container, class Object> bool MyFindFunction( const Container& container, Object& found, bool isMap ){
..
if(!isMap){
found = *iter; // this works for set, but not for map
}
else{
found = iter->second; // this works for map, but not for set
}
..
}