Аналог Python генераторов на C++
Можно ли как-то заставить C++ код работать как-то схоже с кодом на python, который называются генераторы, "не изобретая при этом новую Теорию Относительности".
Например, последовательность Фибоначчи:
def fib():
f = 1
s = 0
while True:
yield s
f, s = s, s+f
k = fib()
for i in range(10):
print(next(k))
Пробовал так, но, думаю, что есть какие-то более "правильные" варианты ?
int fib(){
static int f=1, s=0;
int t=f;
f = s;
s += t;
return s;
}
int main(){
for(int i=0; i<10; ++i)
cout << fib() << ' ';
return 0;
}
Как минимум, мой аналог "одноразовый" (нельзя начать последовательность заново).
Ответы (3 шт):
Например так (с созданием экземпляра объекта и использованием оператора вызова функции):
class Fib {
public:
int operator()()
{
int t = f;
f = s;
s += t;
return s;
}
private:
int f = 1;
int s = 0;
};
int main() {
Fib k;
for (int i = 0; i < 10; ++i)
std::cout << k() << ' ';
}
А я бы вот так сделал :) :
#include <iostream>
using namespace std;
class Fibonacci {
private:
int first = 1;
int second = 0;
int index = 0;
public:
int operator++() {
int t = first;
first = second;
second += t;
++index;
return second;
}
int operator--() {
if (index <= 0) {
index = 0;
first = 1;
second = 0;
return second;
}
int t = second - first;
second = first;
first = t;
--index;
return second;
}
};
int main() {
Fibonacci fib;
for (int i = 0; i < 10; ++i)
cout << ++fib << " ";
cout << endl;
for (int i = 0; i < 12; ++i)
cout << --fib << " ";
cout << endl;
return 0;
}
Результат:
1 1 2 3 5 8 13 21 34 55
34 21 13 8 5 3 2 1 1 0 0 0
Можно добавить всякие функции по типу getByIndex всякие преобразования и т.д. Так же можно сделать класс шаблонным и тогда использовать длинные числа ну или например ullong int. Всякие проверки на переполнения сделать можно.
В недалеком светлом будущем (а пользователям Visual Studio уже сейчас, если включить поддержку Features from the Latest C++ Working Draft) можно будет использовать более каноничные генераторы (с использованием ключевого слова co_yield):
#include <iostream>
#include <coroutine>
#include <experimental/generator>
std::experimental::generator<double> fibonacci(const double ceiling) {
double j = 0;
double i = 1;
co_yield j;
if (ceiling > j) {
do {
co_yield i;
double tmp = i;
i += j;
j = tmp;
} while (i <= ceiling);
}
}
int main() {
for (const auto v: fibonacci(100))
std::cout << v << ' ';
}
(пример собирается в Visual Studio 2019, с включенным Features from the Latest C++ Working Draft, выводит числа Фибоначчи в диапазоне от нуля до ста)