【问题标题】:Why I cannot create a stream iterator?为什么我不能创建流迭代器?
【发布时间】:2019-09-23 14:17:38
【问题描述】:

我应该创建一个看起来像流迭代器的类,以便在增加我的类的对象时可以从输入流中读取。

我已经这样做了:

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)

【问题讨论】:

    标签: c++ istream-iterator


    【解决方案1】:

    问题在于比较in_ != rhs.in_(以及in_ == rhs.in_)。您无法比较流。

    相反,您需要保持某种“是结束迭代器”或“处于文件结束”状态,当您到达文件末尾时设置,并且默认情况下在默认构造中设置迭代器对象。

    【讨论】:

    • 好的,我明白了。你能告诉我如何解决它吗?我只是为了教育目的。
    【解决方案2】:

    作为@Some programmer dude:流对象既不能复制,也不能分配,也不能比较。

    如果您想让它用于某些教育目的,那么您可以在您的班级 istrm_iter 中添加另一个成员,该成员跟踪它绑定的流状态,并在 in/equality 运算符中比较迭代器是否它们的内部状态是好是坏,如果他们两个都好,那么他们是平等的,当他们是off-end时会发生这种情况,否则他们不相等:

    不将迭代器绑定到流的默认构造函数会使内部状态变坏。

    ++ 应该在每个输入运算符之后检查流是否命中EOF 或报告了 IO 错误,因此它将状态设置为错误。这使得它等于使用默认构造函数(作为终端迭代器)构造的那个。

    这是一个简单的建议:

    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;
    }
    

    不,它有效。注:这只是我知道的一个例子,模仿标准库定义的类需要很多东西。

    【讨论】:

      猜你喜欢
      • 2021-10-27
      • 2011-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-10
      • 1970-01-01
      • 1970-01-01
      • 2017-02-09
      相关资源
      最近更新 更多