Unique ID zur Compile Zeit generieren



  • Arcoth schrieb:

    Nicht einmal Vergleiche von zwei identisch hergeleiteten Zeigerwerten sind definiert: Weil diese Zeiger nicht nachweislich auf das selbe Objekt zeigen.

    Dafuq?
    reinterpret_cast T* a -> uintptr_t i -> T* b ist soweit ich weiss sehrwohl definiert, und zwar so dass danach a == b gelten muss.
    Oder meinst du den Fall T* a -> uintptr_t i -> U* b mit T != U?

    Arcoth schrieb:

    Wo liegt also das Problem, zur compile time einen zufälligen Wert zuzuweisen, der für Objekte innerhalb einer TU konsistent ist? Oder ist meine Argumentation oben einfach nicht mit der Praxis kompatibel? Es kann gut sein, dass ein als reachable deklariertes Objekt dann auch durch einen solchen Ausdruck angefasst werden darf. Alles in allem ist die de facto Lage IMO in Ordnung.

    Angesichts der Tatsache dass der Aufwand es zu implementieren um mehrere Grössenordnungen zu hoch wäre, finde ich es auch OK. Was aber nicht heisst dass es nicht praktisch wäre 🙂

    Arcoth schrieb:

    Die nächste Frage wäre, was der TE mit diesem Mechanismus zu lösen versucht. XY halt.

    Richtig. Das wäre interessant.


  • Mod

    hustbaer schrieb:

    Arcoth schrieb:

    Nicht einmal Vergleiche von zwei identisch hergeleiteten Zeigerwerten sind definiert: Weil diese Zeiger nicht nachweislich auf das selbe Objekt zeigen.

    Dafuq?
    reinterpret_cast T* a -> uintptr_t i -> T* b ist soweit ich weiss sehrwohl definiert, und zwar so dass danach a == b gelten muss.

    Ja, das würde ich auch sagen. Ich bin halt von einer sehr wortwörtlichen Exegese ausgegangen, aber die wäre wahrscheinlich sowieso nicht kohärent (bspw. ist das alternative Resultat entschieden negativ, wo man eher unspezifiziertes Verhalten erwarten würde). Und wenn wir vorschreiben, dass obiges funktionieren soll, dann können wir auch keinen zufälligen Wert zuweisen, da nicht über mehrere TUs einheitlich machbar. Du hast Recht. Ich berufe mich allerdings auf meinen (gerade beendeten!) Kaffeeentzug nach der Weissheitszahn-OP, der mich meiner Konzentration beraubt hat :p



  • Arcoth schrieb:

    Du hast Recht. Ich berufe mich allerdings auf meinen (gerade beendeten!) Kaffeeentzug nach der Weissheitszahn-OP, der mich meiner Konzentration beraubt hat :p

    Ich glaube wenn wir zählen wer von uns beiden in den letzten Jahren bezüglich Standard öfter daneben gelegen hat ... würde ich ziemlich alt aussehen. 😉



  • ps: Das reinterpret_cast -Verbot verhindert u.A. auch dass man offsetof standardkonform compile-time-const implementiert. Wobei ich das als einen Spezialfall ansehe der damit gut abgedeckt ist dass der Standard vorschreibt dass es offsetof zu geben hat, und die Implementierung es halt irgendwie magisch bereitstellen muss.


  • Mod

    Selbiges gilt für addressof . Es gibt sogar einen Paper Sketch, der die Konvertierung zu Zeigern auf character types zu erlauben sucht: http://apolukhin.github.io/constexpr_algorithms/reinterpret.html



  • Arcoth schrieb:

    Die nächste Frage wäre, was der TE mit diesem Mechanismus zu lösen versucht.

    Ich bau mir eine kleine Bibliothek, mit der ich SQL Queries zur Compile Zeit aus Klassen generieren kann. Dafür brauche ich einen zufälligen Compile-Time-String, den ich als Namen für mein SQL Feld nutzen kann. (Weil ich unter Umständen die selben Feld Namen in unterschiedlichen Tabellen nutzen werde) Bsp:

    SELECT Table1.Fuu AS MyUniqueIdentifier1, Table2.Fuu AS MyUniqueIdentifier2 FROM ...;
    

  • Mod

    Und wofür muss der String eine Compilezeit Konstante sein?



  • Muss er dann vermutlich eh nicht.

    Das Szenario kann man dann ja schön lösen indem man die Adresse einer statischen Membervariable des Template nimmt, diese dann (ohne constexpr) in einen uintptr_t konvertiert, und dann runtime hex-codiert. (Bzw. einfach den stream insertion operator für void* verwendet.)


  • Mod

    hustbaer schrieb:

    Muss er dann vermutlich eh nicht.

    Das Szenario kann man dann ja schön lösen indem man die Adresse einer statischen Membervariable des Template nimmt, diese dann (ohne constexpr) in einen uintptr_t konvertiert, und dann runtime hex-codiert.

    Und wozu die Konvertierung nach uintptr_t ? Kannst doch direkt auf den Zeiger sprintf 'n?



  • Ja, richtig.
    Oder stream insertion operator für void* (siehe EDIT von mir eben gerade).
    Ist mir dann auch aufgefallen 🙂

    Bzw. wenn die generierten IDs/Strings nicht "stable" zwischen verschiedenen Programmausführungen sein müssen könnte man auch einfach einen Atomic-Counter verwenden um ein function-local-static zu initialisieren. Wobei die Member-Adressen Variante vermutlich so ziemlich universell besser ist.


  • Mod

    Wenn wir aber von Tabellennamen sprechen, könnte man doch gleich die demanglete Version von typeid(x).name() verwenden, oder? Man muss schauen, dass das auch einigermaßen eindeutig ist (am besten vollständig qualifiziert).



  • Ich würde dann eher noch die "rohe" Version verwenden und dann hex-codieren - die ist garantiert eindeutig (und man kann über keine Bugs beim Demangling stolpern).
    Nur: Diese Namen können ganz schnell verflixt lange werden. Ein paar hundert Zeichen sind da nix. Normalerweise nicht das was man als Identifier in Database Statements haben möchte.


Anmelden zum Antworten