用于迭代多重映射的某些元素的设计运算符++

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

我有以下 class 声明:

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()访问外部class是否是一个好的设计?其次,operator++ return 是正确的还是应该 return 仅 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;
}