Почему ряд Фибоначчи с использованием итератора и диапазона выдает ошибку

#c #c 11 #logic #c 17

Вопрос:

Я практикуюсь в фрагментах кода C в учебнике по ускоренному курсу CPP (Глава 8, Упражнение 1), Ссылка ниже не компилируется, и ниже приведена ошибка программы. Было бы полезно, если бы были предоставлены какие-либо предложения или ссылки для понимания. :).

 #include <cstdio>
struct FibonacciIterator {
    bool operator!=(int x) const {
    return x >= current; 
    }
    FibonacciIteratoramp; operator  () {
    const auto tmp = current; 
    current  = last; 
    last = tmp; 
    return *this;
    }
    int operator*() const {
    return current;
    }
private:
    int current{ 1 }, last{ 1 };
};

struct FibonacciRange {
    explicit FibonacciRange(int max) : max{ max } { }
    FibonacciIterator begin() const { 
    return FibonacciIterator{};
    }
    int end() const { 
    return max;
    }
private:
    const int max;
};

int main() {
    for (const auto i : FibonacciRange{ 50 }) {
    printf("%d ", i); 
    }
}

 

Ошибка:

 user@stretch:/tmp$ g   test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:32:46: error: inconsistent begin/end types in range-based ‘for’ statement: ‘FibonacciIterator’ and ‘int’
     for (const auto i : FibonacciRange{ 5000 }) {
                                              ^
test.cpp:32:46: error: conversion from ‘int’ to non-scalar type ‘FibonacciIterator’ requested
test.cpp:32:46: error: no match for ‘operator!=’ (operand types are ‘FibonacciIterator’ and ‘FibonacciIterator’)
test.cpp:3:10: note: candidate: bool FibonacciIterator::operator!=(int) const
     bool operator!=(int x) const {
          ^~~~~~~~
test.cpp:3:10: note:   no known conversion for argument 1 from ‘FibonacciIterator’ to ‘int’
 

Ответ №1:

Ваши begin функции и end функции-члены возвращают разные типы. До C 17 эти типы должны быть одинаковыми, как указано в сообщении об ошибке

ошибка: несогласованные типы начала/конца в инструкции » для » на основе диапазона

Начиная с C 17, это ограничение на циклы range-for было ослаблено

Начиная с C 17, типы the begin_expr и the end_expr не обязательно должны быть одинаковыми, и на самом деле тип the end_expr не обязательно должен быть итератором: его просто нужно сравнивать для неравенства с единицей. Это позволяет ограничить диапазон предикатом (например, «итератор указывает на нулевой символ»).

Поэтому, если вы скомпилируете свой код с помощью C 17, передав -std=c 17 флаг, ваш код будет скомпилирован, предполагая, что он удовлетворяет всем остальным ограничениям, что он и делает.