I am designing a class with several data members and I want to save these data members to a binary file in one part of the project. In another part of the project (an independent binary) I want to load them and "construct the object using them." So in the "saving program" would be something like this:
LoadableClass a(SomeOtherObjectOfSomeOtherClass); // Construct it from another object
std::ofstream BinaryStream("largefile.dat", std::binary);
a.WriteToFile(BinaryStream);
In the other program, I would like to construct it from the file:
std::ifstream BinaryStream("largefile.dat", std::binary);
LoadableClass a(BinaryStream);
a.DoSomeMagic();
The class itself looks contains some matrices that can take up to 1GB of memory.
class LoadableClass {
private:
int rows, cols;
Matrix mat;
public:
LoadableClass(const SomeOtherClass& other); // Construct it from some other class (calculate).
void WriteToFile(std::ofstream& BinSt) const { Write the data to the stream here.}
LoadableClass(std::ifstream BinSt) :
rows{
[&]() -> int {
int temprows;
BinSt.read(reinterpret_cast<char*>(&temprows), sizeof(temprows));
return temprows;
}()
},
cols{
[&]() -> int {
int tempcols;
BinSt.read(reinterpret_cast<char*>(&tempcols), sizeof(tempcols));
return tempcols;
}()
},
mat{
[&]() -> MatrixXd {
MatrixXd tempmat(rows, cols);
BinSt.read(reinterpret_cast<char*>(tempmat.data()), rows * cols * sizeof(double));
return tempmat;
}()
}{}
It seems that this code works. One other aspect of this class is that the data members should never change. Once the object is constructed, they will not change (I could make them const, in fact).
Is this for some reason a bad design? What would be better? I thought that I could do the reading from the file in the body of the constructor rather than in the initializer list. However, the default construction of the matrix is a bit awkward.
Alternatively, I could take care of the reading from the file outside of the class and just have a constructor with all the data members
LoadableClass(const int r, const in c, const MatrixXd m) : rows{r}, cols{c}, mat{m}{}
However, that seems awkward to me, too. The code that constructs the object from the file, would have to know the details of the implementation of LoadableClass and every time its implementation would change, I would have to modify code outside of the class.
So far, I have never seen this complicated initializer list and I am not sure about the possible side effects. Thank you for any ideas.
Edit: I was suggested to use a (de)serialization library. While that would be a feasible solution, I would like to keep a control over the way the data is written to the file as much as possible. I anticipate some performance bottlenecks there in the future. Is it usual to bring an additional library into a project for a single read/write task?