Почему я не могу создать потоковый итератор? - PullRequest
5 голосов
/ 23 сентября 2019

Я должен создать класс итератора потока, похожего на поток, чтобы я мог читать из входного потока при добавлении объекта моего класса.

Я сделал это:

template<class T>
struct istrm_it{
    istrm_it() = default;
    istrm_it(std::istream& in) :
        in_(in), val_(T()) {
        in_ >> val_;
    }
    T val_;
    std::istream& in_ = std::cin;
    istrm_it& operator++() { in >> val_; return *this; };
    istrm_it& operator++(int) { in_ >> val_; return *this; };
    T operator*() { return val_; }
    bool operator==(const istrm_it& rhs)const { return in_ == rhs.in_; }
    bool operator!=(const istrm_it& rhs) const{ return in_ != rhs.in_; }
};

int main(){

    istrm_it<int> it(std::cin), e;
    cout << *it << endl; // ok

    it++; // ok read the next value from the nput stream

    vector<int> vi;
    while (it != e) // the problem here
        vi.push_back(*it++);

    for (auto i : vi)
        std::cout << i << ", ";
    std::cout << std::endl;


    std::cout << std::endl;
}

Что я получаю: Severity Code Description Project File Line Suppression State Error C2678 binary '!=': no operator found which takes a left-hand operand of type 'std::istream' (or there is no acceptable conversion)

Ответы [ 2 ]

7 голосов
/ 23 сентября 2019

Проблема в сравнении in_ != rhs.in_in_ == rhs.in_ также).Вы не можете сравнивать streams .

Вместо этого вам нужно сохранить какое-то состояние "is end end итератор" или "is at end-of-file", которое устанавливается при достижении end-of-file, и который устанавливается по умолчанию в построенном по умолчанию объекте итератора.

1 голос
/ 23 сентября 2019

Как @Some programmer dude: объекты потока нельзя ни копировать, ни назначать, ни сравнивать.

Если вы хотите, чтобы он работал в образовательных целях, вы можете добавить в свой класс другого члена istrm_iter, который отслеживает состояние потока, к которому он привязан, и в операторах in / равенства сравнивать итераторы,их внутреннее состояние хорошее или нет, если оба они хороши, то они равны, и это происходит, когда они равны off-end, иначе они не равны:

Конструктор по умолчанию, который не привязывает итератор кпоток должен сделать внутреннее состояние плохим.

И ++ должен после каждого оператора ввода проверять, достигнет ли поток EOF или сообщил об ошибке ввода-вывода, таким образом, он устанавливает состояние как плохое.что делает его равным построенному с конструктором по умолчанию (как внешний итератор).

Вот простое предложение:

template<class T>
struct istrm_it {
    istrm_it() = default;
    istrm_it(std::istream& in) :
        in_(in), val_(T()),
        is_good_(true) {
        in_ >> val_;
    }
    bool is_good_ = false;
    T val_ = T{};
    std::istream& in_ = std::cin;
    istrm_it& operator++() { in_ >> val_; if (!in_) is_good_ = false; return *this; };
    istrm_it& operator++(int) { in_ >> val_;  if (!in_) is_good_ = false; return *this; };
    T operator*() { return val_; }
    bool operator==(const istrm_it& rhs) const {
        return is_good_ && rhs.is_good_ || !is_good_ && !rhs.is_good_;}
    bool operator!=(const istrm_it& rhs) const{ return !(operator==(rhs)); }
};

и в основном:

int main(){
    istrm_it<int> it(std::cin), e;
    cout << *it << endl;

    vector<int> vi;

    while (it != e)
        vi.push_back(*it++);


    for (auto i : vi)
        std::cout << i << ", ";
    std::cout << std::endl;
}

Нет, это работает.NB. Это всего лишь пример, который я знаю, на самом деле требуется много вещей, чтобы имитировать класс, определенный стандартной библиотекой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...