Reputation: 93
I want to write and read STL Vector of my class type to binary file, but don't understand what's wrong with istream_iterator.
Project rules disallow to use text files,
same as third-party libraries like Boost.
This is 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;
};
This is write method:
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"));
}
And i want to read like this:
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;
}
Compiller says -- Book:no appropriate default constructor available.
Upvotes: 3
Views: 1355
Reputation: 44063
std::istream_iterator<Book>
uses operator>>(std::istream&, Book&)
to read data into objects. Since this operator>>
requires an existing Book
object as parameter (to write the data into), the iterator has to construct one before it can dump the data from the stream into it, and for this it requires a default constructor.
Your Book
class does not have one. The easiest solution to the problem would be to give it one.
In the event that this is not an option (e.g., if Book
as to guarantee invariants that a default constructor cannot provide), you could introduce an intermediate data transfer class that is default-constructible, can be filled with data via operator>>
, and can be converted to Book
. Sketch:
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));
To be sure, this approach is rather cumbersome and essentially duplicates code, and probably it is less hassle to give Book
the default-constructor. However, if Book
cannot be changed in this way, this is a possible workaround.
Upvotes: 4