Итак, предположим, что мы хотим перебрать некоторую функцию над всеми, даже положительных чисел меньше или равно 100. Мы могли бы сделать:Итерация по коллекции без создания коллекции первого
vector<int> v;
for (int i=0; i<=100; i+=2) v.push_back(i);
for_each(v.begin(), v.end(), ourFunction);
Другой простой способ:
for (int i=0; i<=100; i+=2) ourFunction(i);
Теперь предположим, что у нас есть более сложная коллекция, которую мы хотим повторить. Например palindromical чисел (в базе 10) меньше, чем 1000000. Мы могли бы сделать:
inline int tenTo(int power) { int n= 1; for(int i=0; i<power; i++) n*=10; return n; }
vector<int> getPalindromial(int digits, bool firstCall = true,vector<int> &fakePalindromial = vector<int>()) {
if (digits == 1) {
// Base Case 1
vector<int> v;
fakePalindromial.push_back(0);
for (int i=1; i<=9; i++) {
v.push_back(i);
fakePalindromial.push_back(i);
}
return v;
} else if (digits == 2) {
// Base Case 2
vector<int> v;
fakePalindromial.push_back(0);
for (int i=11; i<=99; i += 11) {
v.push_back(i);
fakePalindromial.push_back(i);
}
return v;
} else {
if (firstCall) {
// If this is the first call, we built all the odd lenght numbers and the even length numbers and then we join them and return.
vector<int> v1 = getPalindromial(digits,false);
vector<int> v2 = getPalindromial(digits-1,false);
v1.insert(v1.end(), v2.begin(), v2.end());
return v1;
}
/* Recursive case:
* For each palindromical number with 2 less digits, we add each digit at start and at the end
*/
vector<int> v = getPalindromial(digits-2,false,fakePalindromial);
const int size = fakePalindromial.size();
for (int i=0; i<size; i++) {
const int n = fakePalindromial[i];
int nDigits = 1;
for (int i=0; i< digits-2; i++) {
nDigits *= 10;
}
/* Numbers with leading 0 are not really palindromical, but will be usefull to the functions building higher
* numbers (010 is not palindromical, but it is usefull for building 50105)
*/
int digit = 0;
fakePalindromial.push_back(10*(nDigits*digit + n) + digit);
for (int digit=1; digit<=9; digit++) {
v.push_back(10*(nDigits*digit + n) + digit);
fakePalindromial.push_back(10*(nDigits*digit + n) + digit);
}
}
// Clean the palindromical numbers that we have used
for (int i=0; i<size; i++) {
fakePalindromial.erase(fakePalindromial.begin());
}
return v;
}
}
А потом:
vector<int> v = getPalindromial(6);
for_each(v.begin(), v.end(), ourFunction);
Как мы можем достичь того же, не создавая коллекцию отверстий, а затем итерацию над ним ?
(Примечание: getPalindromial функция может быть проще, это было сделано таким образом, так это более сложным)
Я вроде как итераторы на основе генератора на основе python: каждый вызов не const lambda возвращает 'optional', и когда он терпит неудачу, мы достигли конца. –
Yakk
Это, безусловно, упростит работу, если не понадобится конечный итератор, но я предполагаю, что в рамках C++ фрейм будет взломан. Я попытался реализовать аналогичные генераторы с исключениями, но это не довольно хак. – Anycorn
Вам просто нужно кэшировать одно возвращаемое значение в 'iterator' и читать новое значение при продвижении: это в точности то же самое, что итераторы ввода из потоков Работа. Затем либо используйте 'boost :: iterator_facade', чтобы закончить его, либо выполните беспорядочную работу самостоятельно. – Yakk