设计operator ++用于迭代多图的某些元素

时间:2015-09-12 10:16:50

标签: c++ iterator nested-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()访问外部类是一个好的设计吗?第二,是operator ++返回正确的东西还是应该只返回prime_iterator?另外,你能想到更好的解决方案吗?

2 个答案:

答案 0 :(得分:1)

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

您可以使用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实现 - 它可以免费查看......

答案 1 :(得分:1)

我的谦虚解决方案。 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;
}