为迭代multimap的某些元素设计operator++

Design operator++ for iterating over certain elements of a multimap

本文关键字:元素 operator++ 迭代 multimap      更新时间:2023-10-16

我有以下类声明:

class Dictionnary{
  private:
    map< int,list<string> > data;
  public:
    bool isPrime();
    class prime_iterator{
      private:
        map< int,list<string> >::iterator it;
      public:
        iterator(){}
        prime_iterator & operator++(){
          ++it;
            while(it != data.end() && !isPrime(it->first)){
            ++it;
          }
          return it;
        }
        ...
};

,目的是为map<int,list<string>>的素键提供一个迭代器。我不确定operator++是否实现得很好。

首先,做it != data.end()访问外部类是一个好的设计吗?第二,operator++是否返回正确的结果,还是应该只返回prime_iterator?另外,你能想到更好的解决方案吗?

我的建议是总是尝试在其他地方寻找解决方案-如果没有找到-那么只有自己创造:

可以使用boost::fiter_iterator

对于您的情况,它看起来像这样:

#include <boost/iterator/filter_iterator.hpp>
using DataMap = std::map<int, std::list<std::string>>;
struct is_prime_number {
  bool operator()(const DataMap::value_type& x) { return x.first % 2 == 0; }
}; // I know this is just is_even - not is_prime :D
using DataMapPrimeIter = boost::filter_iterator<is_prime_number, DataMap::iterator>;
inline DataMapPrimeIter only_prime_begin(DataMap& dataMap)
{
    return boost::make_filter_iterator<is_prime_number>(dataMap.begin(), dataMap.end());
}
inline DataMapPrimeIter only_prime_end(DataMap& dataMap)
{
    return boost::make_filter_iterator<is_prime_number>(dataMap.end(), dataMap.end());
}

和用法:

int main()
{
    DataMap dataMap{{1,{"A","B"}}, {2,{"C", "D", "E"}}};
    for (auto i = only_prime_begin(dataMap), end = only_prime_end(dataMap); i != end; ++i)
    {
        std::cout << i->first << i->second.front() << std::endl;
    }
}

如果你想有自己的实现,或者你不能在你的项目中使用boost -那么看看boost实现-它是免费的看…

我的拙见。typedef只是为了方便。

#include <iterator>
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <algorithm>
typedef std::map<int, std::string> map_t;
class Dictionary {
private:
    map_t& m_map;
public:
    class prime_iterator {
    public:
        prime_iterator( map_t::iterator begin, map_t::iterator end )
            : m_current(begin), m_end(end) {
            runUntilPrime();
        }
        prime_iterator& operator++() {
            m_current++;
            runUntilPrime();
            return *this;
        }
        bool operator != (prime_iterator other) {
            return other.m_current != m_current;
        }
        map_t::value_type& operator* () {
            return *m_current;
        }
    private:
        map_t::iterator m_current;
        map_t::iterator m_end;
        bool isPrime(int x) {
            std::vector<int> primes = { 1, 2, 3, 5, 7, 11, 13, 17 };
            return std::find( primes.begin(), primes.end(), x ) != primes.end();
        }
        void runUntilPrime() {
            while( m_current != m_end && !isPrime(m_current->first) ) {
                m_current++;
            }
        }
    };
    Dictionary( map_t& tmap )
        : m_map(tmap) {}
    prime_iterator begin() {
        return prime_iterator( m_map.begin(), m_map.end() );
    }
    prime_iterator end () {
        return prime_iterator(m_map.end(), m_map.end());
    }
};
int main( int argc, char** argv ) {
    map_t map;
    map.emplace(0, "zero");
    map.emplace(1, "one");
    map.emplace(2, "two");
    map.emplace(3, "three");
    map.emplace(4, "four");
    map.emplace(5, "five");
    map.emplace(6, "six");
    map.emplace(7, "seven");
    map.emplace(8, "eight");
    map.emplace(9, "nine");
    map.emplace(10, "ten");
    map.emplace(13, "thirteen");
    Dictionary dict( map );
    for( auto p : dict ) {
        std::cout << p.first << "t" << p.second << std::endl;
    }
    return 0;
}