One operator<< to rule them all



  • Hallo,

    angenommen ich habe aus welchem Grund auch immer eine kleine Klasse BinaryFile . Diese Klasse bietet ein write(const std::byte* buf, std::size_t count) und ein read(std::byte* buf, std::size_t count) . Ziel: Binäres lesen/schreiben von Dateien, schön schnell direkt mit OS Methoden und angenehm zu verwenden. Evtl. auch mal mit MemoryMappedFiles oder so

    Nun dachte ich, geil, wenn ich jetzt jeden beliebigen POD Typ serialisieren möchte, schreib ich einfach noch so einen:

    template<class T>
    typename std::enable_if<std::is_pod<T>::value, BinaryFile&>::type
    operator<<(BinaryFile& f, const T& val)
    {
        return f.write(reinterpret_cast<const std::byte*>(&val), sizeof(T));
    }
    

    Ist das ok oder schieß ich mir da irgendwie in den Fuß? Rein spontan fällt mir z.B. const char* ein. Woher weiß ich ob da jemand nur einen Zeiger abspeichern will, oder einen 200-Zeichen langen C String?



  • HarteWare schrieb:

    Woher weiß ich ob da jemand nur einen Zeiger abspeichern will, oder einen 200-Zeichen langen C String?

    Was tu ich heute mit einer Speicheradresse von gestern? 😕



  • Es gibt auch type traits für Pointer-Typen ( std::is_pointer ).



  • HarteWare schrieb:

    Woher weiß ich ob da jemand nur einen Zeiger abspeichern will, oder einen 200-Zeichen langen C String?

    Dein Compiler weiß, ob es ein Pointer ist:

    template<class T> 
    typename std::enable_if< std::is_pod<T>::value && !std::is_pointer<T>::value, BinaryFile&>::type 
    operator<<(BinaryFile& f, const T& val) 
    { 
        return f.write(reinterpret_cast<const std::byte*>(&val), sizeof(T)); 
    }
    


  • Der Compiler weiss aber nicht ob der const char* auf nen einzelnen char zeigt oder auf ein char Array mit Fixgrösse oder nen nullterminierten String.

    @HarteWare
    Zeiger wirst du mit so einem trivialen Ansatz ebensowenig sinnvoll behandeln können wie structs die Zeiger enthalten.
    Guck dir das Thema Serialisierung an. Dazu gibt's etliche Libraries. Je nachdem was man alles abdecken können möchte ist der dazu nötige Code von trivial (=das was du machst) bis einigermassen komplex.


  • Mod

    Da kann man hustbaer nur zustimmen: Integriere deine I/O Interface mit einer Serialisierungs-Bibliothek wie Boost.Serialisation. Kann nur besser werden. I.A. wäre reflection ein für dieses Thema sehr interessantes Feature: wenn wir feststellen können, dass ein Objekt nur public Member hat, können wir mithilfe einiger Policies entscheiden, wie die verschiedenen Arten von Typen gehandhabt werden sollen.



  • OK stimmt, das wird nicht gut funktionieren in der Form. Das wird mir zu kompliziert mit Zeigern in structs etc. (v.a. das was boost kann), dann doch lieber für jeden Datentyp einzeln.


Anmelden zum Antworten