创建STL映射键迭代器

Mr.*_*Boy 7 c++ stl

通常,您有一个映射map<string,X>,其中键是映射值的名称,您需要一个API,让消费者可以看到所有名称...例如填充GUI列表框.您可以构建一个向量并将其作为API调用返回,但这样效率很低.您可以只返回对地图的引用,但随后也可以访问这些值,您可能不希望这样.

那么你怎么能编写一个兼容的类KeyIterator,它包装map并提供对该map中键的标准迭代器访问.

例如:

map<string,X> m= ...
KeyIterator<string> ki(m);
for(KeyIterator<string>::iterator it=ki.begin();it!=ki.end();++it)
 cout << *it;
Run Code Online (Sandbox Code Playgroud)

KeyIterator应该是轻量级的,因此您可以从几乎没有开销的方法返回它.

编辑: 我不确定我是否完美解释,让我给出一个更好的用例(半伪):

class PersonManager
{
 private:
  map<string,Person> people;
 public:
  //this version has to iterate the map, build a new structure and return a copy
  vector<string> getNamesStandard();

  //this version returns a lightweight container which can be iterated
  //and directly wraps the map, allowing access to the keys
  KeyIterator<string> getNames();
};

void PrintNames(PersonManager &pm)
{
 KeyIterator<string> names = pm.getNames();
 for(KeyIterator<string>::iterator it=names.begin();it!=names.end();++it)
  cout << *it << endl;
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*som 3

template<typename iterator_type>
class KeyIterator
{
    iterator_type iterator;
public:
    typedef typename std::iterator_traits<iterator_type>::value_type::first_type value_type;
    KeyIterator(iterator_type i) : iterator(i) {}
    value_type operator*() { return iterator->first; }
    KeyIterator & operator++() { ++iterator; return *this; }
    bool operator!=(const KeyIterator & right) const { return iterator != right.iterator; }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

编辑:看到您的编辑后,我意识到这并不完全是您所要求的。你把你的类称为 KeyIterator ,这让我很困惑,更合适的名称是 KeyContainer 。您将无法仅在键类型上对其进行模板化,因为它必须包含对地图的某种引用;您将需要地图的完整定义。

您的请求使问题变得过于复杂,因为您必须定义两种不同的类型,KeyIteratorKeyIterator::iterator

这是使用我的类的示例代码:

class PersonManager
{
private:
    map<string,Person> people;
public:
    //this version has to iterate the map, build a new structure and return a copy 
    vector<string> getNamesStandard(); 

    //this version returns a lightweight container which can be iterated 
    //and directly wraps the map, allowing access to the keys 
    KeyIterator<map<string,Person>::iterator> getNamesBegin(); 
    KeyIterator<map<string,Person>::iterator> getNamesEnd(); 
}; 

void PrintNames(PersonManager &pm) 
{ 
    KeyIterator<map<string,Person>::iterator> it = pm.getNamesBegin();
    KeyIterator<map<string,Person>::iterator> end = pm.getNamesEnd();
    for(it; it!=end; ++it) 
        cout << *it << endl; 
}
Run Code Online (Sandbox Code Playgroud)