문제

I have a bunch of structs to read from various files, to avoid defining a repetitive operator>> and operator<< for each and every one, I thought about using the following:

#include <fstream>

#pragma pack(push, 1)

template<typename Derived>
struct Base
{
    friend std::istream& operator>>(std::istream& stream, Base& base)
    {
        return stream.read(reinterpret_cast<char*>(&base), sizeof(Derived));
    }
    friend std::ostream& operator<<(std::ostream& stream, Base const& base)
    {
        return stream.write(reinterpret_cast<char const*>(&base), sizeof(Derived));
    }
};

struct Foo : public Base<Foo>
{
    int32_t i;
    int8_t j, k, l;
    uint16_t m;
};

struct Bar : public Base<Bar>
{
    int32_t i;
    uint16_t m;
};

#pragma pack(pop)

int main()
{
    Foo foo;
    Bar bar;

    std::ifstream("foobarout", std::ios::binary) >> foo >> bar;
    std::ofstream("foobarout", std::ios::binary) << foo << bar;
}

Is reading / copying simple POD objects like the above using a pointer to their base class well-defined (at least within the scope of the single platform I'm running on, I realize this isn't necessarily portable), or am I treading on thin ice?

도움이 되었습니까?

해결책

I would say it is not a good solution.

It will work, but from a client implementer's point of view it looks like you will have these operators defined, but then they depend on the streams being in binary mode (which is not explicit or suggested by your interface - don't do that) and it requires the use of reinterpret_cast (don't do that either). Your restriction to POD types will be hidden as well, unless you drop comments somewhere ("// DO NOT declare non-POD types here").

If you add non-POD types (or use non-binary streams), the errors generated will be silent data corruptions.

You are better off with a separate implementation for each of them; This will not impose any constraints with working with PODs either and the implementation will respect the principle of least surprise.

다른 팁

Depending on your use case, you might also want to take a look at the Boost Serialization Library. While this may seem to be overkill for simple use cases, I found this library to be very flexible for storing objects of varying complexities.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top