USCiLab/cereal

Cerealizing a file offset of type `std::streampos`?

Opened this issue · 4 comments

Hello! I'm trying to serialize a std::streampos variable, but am uncertain of how I can do this. If I try and simply archive it, I am told there is no function available for serializing it. I can cast it to an int64_t and then it will serialize without issue, but then it is not able to read and store the variable properly and I am left with uninitialized variables instead of the proper std::streampos value.

Any insights would be appreciated!

Looking at https://en.cppreference.com/w/cpp/io/fpos, it seems like you should be able to initialize by casting the int to std::streamoff when calling the constructor.

Hello @AzothAmmo! Thanks for your suggestion and sorry for the late response.

What I'm currently doing is the following:

class X
{
private:
    std::streampos position{};

public:
    template <class Archive>
    void serialize(Archive & ar)
    {
        ar(static_cast<std::streamoff>(this->position));
    }
}

This seems to work, and I can both archive data and read archived data without an issue.
However, I'm curious as to what happens when I'm reading archived data. I assume the archived position of type std::streamoff is internally cast to std::streampos type, with a default mbstate_t representing the initial conversion state. Is that correct?

Hi @AzothAmmo, I'm still dealing with this issue and was wondering if you could offer any more insight.

The workaround I proposed earlier doesn't actually work. It writes fine, by casting the std::streampos variable to std::streamoff, but when reading the file back in, it doesn't correctly assign the variable. Instead, I'm left with whatever the default initialization of the variable was (uninitialized in the above example, but std::streampos position{-1} in my code).

I have also tried separating the serialize function as such:

template <class Archive>
void save(Archive & ar) const
{
    archive(static_cast<std::streamoff>(this->position)); // Cast position to streamoff
}

template <class Archive>
void load(Archive & ar)
{
    archive(this->position); // Do not cast, instead load directly into the streampos variable.
}

Unfortunately this produces a compiler error complaining that no serialization functions were found?

Thanks for any help!

cjh1 commented

I am also interesting in a solution to this, thanks.