2016-11-26 2 views
3

Я хочу написать и прочитать STL-вектор моего типа класса в двоичном файле, но не понимаю, что случилось с istream_iterator.
Правила проекта запрещают использовать текстовые файлы, такие же, как сторонние библиотеки, такие как Boost.Построение вектора настраиваемого типа с помощью istream_iterator

Это 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;  
} 

Compiller говорит - Книга: нет подходящего конструктора по умолчанию.

ответ

3

std::istream_iterator<Book> использует operator>>(std::istream&, Book&) для считывания данных в объекты. Поскольку для этого operator>> требуется существующий объект Book в качестве параметра (для записи данных в), то итератору необходимо его построить, прежде чем он сможет выгрузить данные из потока в него, и для этого ему нужен конструктор по умолчанию.

Ваш Book класс не имеет. Самое простое решение проблемы - дать ей одно.

В случае, если это не опция (например, если Book, чтобы гарантировать инварианты, которые конструктор по умолчанию не может предоставить), вы можете ввести промежуточный класс передачи данных, который по умолчанию является конструктивным, может быть заполнен данными через 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 не может быть изменено таким образом, это возможное обходное решение.

+0

Огромное спасибо, это помогло мне! – Zulcom