我有一个基于我在Eratosthenes筛选中在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;
}
但是因为基于范围的循环更容易阅读并且阻止使用运算符*,所以我想要使用它,所以我的问题是:是否有办法使基于范围的循环使用另一个运算符而不是!=(在这种情况下&lt;)?也许overloard primes_range的特定函数或专门化比较器?
答案 0 :(得分:2)
除了在end()
方法上完成整个工作之外,迭代器必须在每次调用operator++
时生成下一个素数,然后在调用operator*
时返回它们。因此,迭代器类的方案可能是:
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++
支持“获取下一个”操作但不通过索引进行随机访问的操作。在迭代器类中声明此类别字段是一种很好的做法,以便提示有关与迭代器一起使用的最佳算法的标准库方法。答案 1 :(得分:0)
以下是迭代器的完整示例。我忘记在上面提到operator!=
需要range based for
才能工作,因为它必须将当前迭代器与end()
方法的结果进行比较。在下面的代码中,您只需将算法的正确实现放在generate_next_prime
函数中,或者根据需要将其放在casses中。
#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;
}
答案 2 :(得分: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);
}
};