使用 istream_iterator 构建自定义类型的向量

Constructing a vector of custom type with istream_iterator

我想将我的 class 类型的 STL Vector 写入和读取到二进制文件,但不明白 istream_iterator.
有什么问题 项目规则不允许使用文本文件, 与 Boost 等第三方库相同。

这是Book.h:

class Book{
    public:
    Book(const std::vector<Book>& in_one_volumes,const std::string& title,
    const std::string& author,const int pagecount,const int price,const std::string& date);
    private:
    std::vector<Book> inOneVolumes;
    std::string title;
    std::string author;
    int pagecount;
    int price;
    std::string date;
};

这是写法:

void writeBook(std::vector<Book> books) {
    std::ofstream binOut("book.bin", std::ios::binary);
    std::copy(books.begin(), books.end(),
        std::ostream_iterator<Book>(binOut, "\n")); 
}

我想这样读:

std::vector<Book> readBooks() {
    std::vector<Book> toReturn;
    std::ifstream BinIn("book.bin", std::ios::binary);
    std::istream_iterator<Book> file_iter(BinIn);
    std::istream_iterator<Book> end_of_stream;
    std::copy(file_iter, end_of_stream, std::back_inserter(toReturn));
    return toReturn;    
}

编译器说 -- Book:no 合适的默认构造函数可用。

std::istream_iterator<Book> 使用 operator>>(std::istream&, Book&) 将数据读入对象。由于此 operator>> 需要一个现有的 Book 对象作为参数(将数据写入其中),因此迭代器必须先构造一个,然后才能将流中的数据转储到其中,为此它需要一个默认构造函数。

您的 Book class 没有。解决这个问题最简单的方法就是给它一个。

如果这不是一个选项(例如,如果 Book 以保证默认构造函数无法提供的不变量),您可以引入默认的中间数据传输 class -可构造,可以通过operator>>填充数据,并可以转换为Book。素描:

class TransferBook {
public:
  // To read data from stream
  friend std::istream &operator>>(std::istream &in, TransferBook &dest);

  // Conversion to Book. Use the non-default Book constructor here.
  operator Book() const {
    return Book(all the data);
  }

private:
  // all the data
};

...

std::vector<Book> books;
std::ifstream file;

// Note that books contains Books and the iterator reads TransferBooks.
// No Book is default-constructed, only TransferBooks are.
std::copy(std::istream_iterator<TransferBook>(file),
          std::istream_iterator<TransferBook>(),
          std::back_inserter(books));

可以肯定的是,这种方法相当麻烦并且本质上是重复代码,并且给 Book 默认构造函数可能不那么麻烦。但是,如果无法以这种方式更改 Book,则这是一种可能的解决方法。