Template C ++:如何访问std :: map和std :: set的迭代器值?

时间:2015-06-16 08:23:10

标签: c++ templates dictionary stl set

我有一个特定的搜索功能。因为它在std::setstd::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 ..

3 个答案:

答案 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);

LIVE DEMO

答案 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
   }
..
}