std::tuple Signatur als hash key



  • Ist jemand schon mal über eine Elegante Möglichkeit gestolpert, aus einer tuple Signatur sowas wie einen Hash Key oder etwas ähnliches zu machen? Oder auch etwas, was man abspeichern und später vergleich könnte.

    Was mir spontan einfällt, wäre eine Liste von ints und ein Funktonstemplate, das jeweils bei der ersten Instanziierung einen globalen Counter hochzählt und den dann als ID für den Typen zurückgibt. Bin aber noch nicht ganz glücklich mit der Idee, vielleicht kennt auch jemand was viel besseres.



  • Hi!

    Mechanics schrieb:

    Was mir spontan einfällt, wäre eine Liste von ints und ein Funktonstemplate, das jeweils bei der ersten Instanziierung einen globalen Counter hochzählt und den dann als ID für den Typen zurückgibt. Bin aber noch nicht ganz glücklich mit der Idee, vielleicht kennt auch jemand was viel besseres.

    Damit wäre ich auch nicht ganz zufrieden, weil dann die IDs von der Instanziierungsreihenfolge abhinge.
    Leider kann ich auch keine fertige Lösung anbieten, aber ich habe kürzlich zwei Vorträge gesehen, deren Ideen sich wahrscheinlich zu dem kombinieren lassen,
    was dir wohl optimalerweise vorschwebt (könnte aber ganz schön aufwendig werden, dafür wahrscheinlich ziemlich cool wenn man es einmal am Laufen hat):

    https://www.youtube.com/watch?v=8AjRD6mU96s&t=14m

    Hier stellt Jason Jurecka u.a. eine Methode vor, mit der sich Klassen/Structs automatisiert versionieren lassen, indem ein Hash über constexpr -Ausrücke generiert wird,
    bei denen die Struktur der Klasse die berechnungsgrundlage bildet. Die dafür notwendige Reflexion (die ja leider noch nicht diret von C++ unterstützt wird) implementiert er
    mit einer klassischen, jedoch leider recht unschönen Makro-Methode.

    https://www.youtube.com/watch?v=abdeAew3gmQ

    In diesem Vortrag stellt Boost-Entwickler Antony Polukhin abgefahrene Template-Magie vor, mit der man auch ohne selbstgestrickte Reflexion via Makro-Geraffel die innere
    Struktur zumindest von POD-Strukturen auswerten kann (wie weit sich das auf beliebige Klassen ausdehnen lässt kann ich nicht sagen).

    Ich habe beide Vorträge nur überflogen und mich noch nicht mit den Details auseinandergesetzt, daher weiss ich nicht was damit wirklich machbar ist.
    Die Methoden stehen allerdings auf meiner Liste der Techniken, die ich mir mal genauer ansehen werde, wenn ich mal einen Hash über beliebige Klassenstruktur bilden,
    oder automatisiert und ohne externe Tools reproduzierbar eindeutige IDs für meine Klassen generieren möchte.

    Hoffe das hilft weiter und entpuppt sich nicht als Holzweg,
    Finnegan



  • Ich schau mir zur Zeit eh nebenbei die CppCon 2016 Videos an, bis zu den beiden bin ich noch nicht gekommen. Werde ich mir dann bei Gelegenheit auf jeden Fall auch anschauen.
    Ich hätt aber gehofft, dass jemand schon eine einfachere, fertige Lösung hat 🙂



  • Mechanics schrieb:

    Ich schau mir zur Zeit eh nebenbei die CppCon 2016 Videos an, bis zu den beiden bin ich noch nicht gekommen. Werde ich mir dann bei Gelegenheit auf jeden Fall auch anschauen.
    Ich hätt aber gehofft, dass jemand schon eine einfachere, fertige Lösung hat 🙂

    Der Jurecka-Vortrag geht leider nicht besonders ins Detail, aber der Ansatz ist interessant. Wäre schon cool wenn z.B. solche Sachen hier automagisch, ohne Boilerplate-Code funktioniern würden:

    shared_ptr<Base> instance = createInstance<Base>(type_hash);
    serialize(stream, instance);
    instance = deserialize<Base>(stream);
    print(*instance);
    

    ...oder was auch immer dir für konkrete Dinge vorschweben, die man mit diesem Hash machen könnte.
    Bisher ist mir jedenfalls kaum etwas untergekommen was andere Sprachen haben, und das man mit C++ nicht auch irgendwie umsetzen kann.
    Ist meist nur eine Frage auf was für abgefahrene Tricks und welchen Template-Horror man sich einlassen will 😉

    Finnegan



  • Finnegan schrieb:

    ...oder was auch immer dir für konkrete Dinge vorschweben, die man mit diesem Hash machen könnte.

    Type Erasure... Ich hab auch noch keine ganz konkreten Vorstellungen, aber z.B. Template Klassen oder Funktionen, die hinter Type Erasure Wrappern verwaltet werden, und dann will ich aber nach passenden Instanzen suchen. Da wärs gut, wenn man einen Hash über die passenden Typen machen könnte.

    Finnegan schrieb:

    Bisher ist mir jedenfalls kaum etwas untergekommen was andere Sprachen haben, und das man mit C++ nicht auch irgendwie umsetzen kann.

    Das trifft wohl am ehesten auf Reflection zu. Mit Reflection kann man schon sehr vieles anstellen. Muss man nicht unbedingt, ist nicht unbedingt die schnellste/beste Lösung, aber man kanns. Und bevor man in C++ anfängt, sowas mit Macros/Templates/Code Generierung nachzubauen, lässt man es meist doch bleiben und machts von Hand.



  • Finnegan schrieb:

    Damit wäre ich auch nicht ganz zufrieden, weil dann die IDs von der Instanziierungsreihenfolge abhinge.

    Ich glaube, da kommt man nicht drum rum. Spätestens, wenn man das Dll-übergreifend haben will, und das will ich, kanns nur noch von der Instanziierungsreihenfolge abhängen, und wahrscheinlich gibts auch keine andere Lösung (Template Tricks usw. helfen auch nicht weiter, wenn man die Dlls unabhängig voneinander baut).
    Kann mir grad auch nicht vorstellen, wie man das performanter machen könnte. Man bräucht einen globalen atomaren Counter, gefällt mir auch nicht, aber mir fällt da nichts anderes ein.



  • Mechanics schrieb:

    Ich glaube, da kommt man nicht drum rum. Spätestens, wenn man das Dll-übergreifend haben will, und das will ich, kanns nur noch von der Instanziierungsreihenfolge abhängen, und wahrscheinlich gibts auch keine andere Lösung (Template Tricks usw. helfen auch nicht weiter, wenn man die Dlls unabhängig voneinander baut).

    Nun, man kann die IDs klassisch "manuell" vergeben und für jeden Typ fest eincodieren (siehe z.B. COM und die GUIDs) bzw. reproduzierbar mit externen Tools automatisch generieren,
    oder man schafft es irgendwie die automatisch mit reinem C++ zu erzeugen:

    hash(<projekt-id>#<klassen-name>#<klassen-layout>) oder hash(<projekt-id>#<klassen-name>#<manuell-vergebene-versionsnummer>)

    wobei die Hash-Funktion natürlich de facto kollisionsfrei sein sollte (irgendein kryptografischer Hash). Die Videos legen schon nahe, dass sowas durchaus als constexpr -Ausdruck machbar wäre.
    Sowas würde natürlich auch reproduzierbar DLL-übergreifend funktionieren und nicht davon abhängen, wie der Code ausgeführt wird.

    Das ist aber wie gesagt wahrscheinlich ziemlich aufwändig und für deine Zwecke möglicherweise Overkill. Denke wenn sich keine simple Lösung auftut, fährst du wohl besser mit deiner spontanen Idee.

    Ich habe derzeit hauptsächlich Interesse an so einem Mechanismus weil ich Objekte gerne in Dateien/Datenbanken/Netzwerkpaketen mit möglichst wenig Overhead und Boilerplate-Code serialisieren/deserialisieren möchte.
    Dazu möchte ich leicht erkennen können welche Klasse und welche Version ich in einem Byte-Strom gerade vorliegen habe - egal ob die Software gerade auf einem PC, einer Spielkonsole oder einem Smartphone läuft, oder
    ob sie mit einem völlig anderen Compiler gebaut wurde oder die Initialisierungsreihenfolge anders war, weil der Code umstrukturiert wurde, die Klassen allerdings kompatibel geblieben sind. Habe vor einiger Zeit mal für ein
    Spieleprojekt in C# recht nette eigene hierarchische Dateiformate mit solchen Techniken zusammengebaut, in denen relativ komplexe 3D-Modelle mit Meshes, Skeletten, Materialien (eingebettet oder Referenzen auf externe -
    inkl. Texturen/Farben/Shader), Animationen und Daten für Physiksimulation kompakt in einer Datei gespeichert werden konnten (oder gleich mehrere solcher Modelle in einem Paket). Natürlich hat die Reflexion in C# das ganze
    sehr vereinfacht, dennoch wollte ich sowas schon länger mal auch mit C++ umsetzen - das schöne daran ist, dass sich die Dateiformate dabei mit dem Klassendesign quasi von selbst definieren 😉



  • Hast du dieses Video schon gesehen?

    https://www.youtube.com/watch?v=FPUBjPYBsGI&list=PLHTh1InhhwT7J5jl4vAhO1WvGHUUFgUQH&index=29

    Ich habs auch noch nicht gesehen, aber hört sich vom Titel her so an, als ob das was ähnliches sein könnte.


Anmelden zum Antworten