Как перегрузить операторы >> и << для разного типа файлов
У меня есть структура на подобии такой :
struct Product
{
int code;
char name[10];
int price;
};
Я хочу, чтобы она могла записываться в файлы как бинарного формата, так и файлы обычного формата.
Перегрузил операции для бинарного формата :
std::ofstream& operator<<(std::ofstream& out, const Product& product) {
out.write((char*)&product.code, sizeof(product.code));
out.write((char*)&product.name, sizeof(product.name));
out.write((char*)&product.price, sizeof(product.price));
return out;
}
std::ifstream& operator>>(std::ifstream& in, Product& product) {
in.read((char*)&product.code, sizeof(product.code));
in.read((char*)&product.name, sizeof(product.name));
in.read((char*)&product.price, sizeof(product.price));
return in;
}
Однако как их перезагрузить и для обычного формата? Ибо синтаксис в бинарном файле и синтаксис в обычном файле различаются, из-за чего у меня на выходе выходит непойми что.
Ответы (1 шт):
Хороший вопрос, на который, как мне кажется, нет хорошего ответа в рамках потоков С++
Есть следующие механизмы, которые вроде как призваны управлять форматом вывода, но они не помогут:
- i/o манипуляторы вроде
std::boolalpha. Меняют состояние потока, устанавливая соотвествующийstd::ios_base::fmtflags. Свой флаг добавить к стандартным нельзя - режим открытия файла
binary. тут проблема с эффективностью и валидностью приведения произвольногоostreamкofstream(в общем случае оператор << следует писать дляostreamвообще, а не дляofstream), плюсbinaryрежим не для этого, и подобное нарушает принцип наименьшего удивления
Как воркэраунд, выглядящий не очень большим злом, я бы предложил сделать отдельные типы со ссылочной сематникой, сериализующие Product. Например шаблонные SerializeAsText<T> и SerializeAsBinary<T> со специализациями SerializeAsText<Product> SerializeAsBinary<Product>. Ну или не шаблонные.
Как совсем костыли, скрытое состояние потока в мапе, в глобальной переменной или thread local storage переменной.
В библиотеках сериализации, вроде boost serialization, бинарность сериализации данных является свойством потока, клиентский код просто делает out << product.code (или даже s & product.code при совмещенной реализации сериализации и десериализации)