繁体   English   中英

基于范围的循环使用另一个运算符

[英]Range-based loop use another operator

我有一个素数生成器,基于我在Eratosthenes的Sieve中在python中看到的内容,因此该生成器基本上生成具有良好性能的素数。

我想要的是在素数范围内使用基于范围的循环,所以这是我所做的:

//Consider prime_generator a class with both operator*, operator!= and operator< overloaded

class primes_range {
private:
    unsigned int max;
public:
    primes_range(unsigned int max) : max(max) {}
    prime_generator begin() const {
        return prime_generator(); //so this generator begin from 2 to
                                  //infinity and beyond but of course
                                  //all primes
    }
    prime_generator end() const {
         prime_generator result;
         for (:*result < max; ++result) {} //so this thing actually create a 
                                           //generator and increment it until it
                                           //gives the first prime number 
                                           //above max so it basically do
                                           //all the work that I don't
                                           //want it to do now
         return rest;
    }
};

因此,在我的主要文章中,我想使用基于范围的循环,这就是primes_range类的重点。

int main() {
    for (auto && i : primes_range(10)) { //So here, this is silly because
                                         //the range-based loop will use end()
                                         //wich will calculate all the prime
                                         //numbers at the very beginning
                                         //and i will increment apart from
                                         //this starting process
        cout << i << endl;
    }
    return 0;
}

当然,我可以使用一个简单的循环:

int main() {
    for (prime_generator pg; *pg < 10; ++pg) {
        cout << *pg << endl;
    }
    return 0;
}

但是,由于范围基循环更易于阅读并且禁止使用运算符*,因此我想改用它,所以我的问题是:有没有一种方法可以使范围基循环使用比!=(在这种情况下<)? 也许覆盖了primes_range的特定功能或专门设计了比较器?

迭代器必须在每次对operator++调用时生成下一个素数,然后在对operator*的调用中返回它们,而不是对end()方法进行全部工作。 因此,您的迭代器类的方案可能是:

class prime_generator {
   typedef std::forward_iterator_tag iterator_category;
   int cur;
   prime_generator& operator++() {
      cur = GenerateNextPrime();
      return *this;
   }
   int operator*() {
      return curr;
   }
};

笔记:

  • 为了使基于范围的工作正常,您至少需要在迭代器类上具有以上签名的operator++operator*
  • 在迭代器类中声明的forward_iterator_tag告诉您正在创建哪种迭代器。 在这种情况下,前向迭代器是一种通过operator++ “获取下一个”操作的operator++但例如不通过索引进行随机访问。 最好在迭代器类中声明此类别字段,以提示有关与迭代器一起使用的最佳算法的标准库方法。

这是关于迭代器的完整示例。 我在上面忘了提到您需要使用operator!=来工作的range based for因为它必须将当前迭代器与end()方法的结果进行比较。 在下面的代码中,您只需要将正确的算法实现放置在generate_next_prime函数中,或根据需要将其放置在casse中即可。

#include <iostream>
#include <iterator>

int generate_next_prime(int previous) {
    // TODO: a correct one!
    return previous + 1;
}

class prime_generator {
    int limit;

public:

    prime_generator(int limit)
        : limit(limit) {}

    class iterator {
        int cur, limit;

    public:

        typedef std::forward_iterator_tag iterator_category;

        iterator(int cur, int limit)
            : cur(cur), limit(limit) {}

        iterator& operator++() {
            cur = generate_next_prime(cur);
            return *this;
        }   

        bool operator==(const iterator &other) {
            // NOTE: for the primes application maybe you should
            // use >= instead of == to ensure cur will not pass limit
            // silently, or do something more elaborate
            return cur == other.cur &&
                   limit == other.limit;
        }

        bool operator!=(const iterator &other) {
            return !(*this == other);
        }   

        int operator*() {
            return cur;
        }   
    };  

    iterator begin() {
        return iterator(2, limit);
    }

    iterator end() {
        return iterator(limit, limit);
    }
};

int main() {
    for (auto p : prime_generator(5))
        std::cout << p << std::endl;

    return 0;
}

根据您告诉我的内容,我来介绍一种解决方案,它基本上是一个适配器。

class primes_range {
private:
    unsigned int max;

    class limited_prime_generator {
    private:
        prime_generator pg;
        unsigned int limit;
        bool reachedLimit;

    public:
        limited_prime_generator(unsigned int limit, bool reachedLimit = false) : pg(), limit(limit), reachedLimit(reachedLimit) {}

        limited_prime_generator & operator++() {
            if (not reachedLimit) {
                reachedLimit = *(++pg) >= limit;
            }

            return *this;
        }
        bool operator!=(limited_prime_generator const & lpg) const {
            return operator*() != *lpg;
        }
        unsigned int operator*() const {
            if (reachedLimit)
                return limit;
            else
                return *pg;
        }
    };

public:
    primes_range(unsigned int max) : max(max) {}

    limited_prime_generator begin() const {
        return limited_prime_generator(max);
    }

    limited_prime_generator end() const {
        return limited_prime_generator(max, true);
    }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM