void* vs Templates (Split aus "Prozentuale Verteilung der Datentypen")



  • Das ist nicht das Thema dieses Threads. Kann das ein Mod splitten?



  • Der Tobi schrieb:

    void-Pointer kann man sehr wohl in C++ brauchen...

    Zeig mir ein sinnvolles Beispiel für void* (OHNE eine Bibliotheksfunktion zu benutzen, die das fordert), wo man nicht genauso gut mit Templates arbeiten kann.

    operator new



  • Der Tobi schrieb:

    void-Pointer kann man sehr wohl in C++ brauchen...

    Zeig mir ein sinnvolles Beispiel für void* (OHNE eine Bibliotheksfunktion zu benutzen, die das fordert), wo man nicht genauso gut mit Templates arbeiten kann.

    void* macht insbesondere zusammen mit templates Sinn: Type Erasure...



  • dot schrieb:

    void* macht insbesondere zusammen mit templates Sinn: Type Erasure...

    👍



  • Hat mal jemand ein Beispiel wo man fuer Type Erasure einen void* braucht?



  • void* brauchts nicht. operator new könnte genauso gut char* zurückgeben, weil er ein Byte-Array allokiert.

    Zur Type Erasure ist mir auch noch nichts eingefallen, denn dann müsste man irgendwie mit rohen Pointern herumhantieren.

    => der einzige Zweck von void* ist eine saubere Definition von reinterpret_cast<>.



  • a void able schrieb:

    operator new könnte genauso gut char* zurückgeben, weil er ein Byte-Array allokiert.

    In einem anderen Thread habe ich letztens erst gezeigt, dass char nicht einen Byte groß sein muss.



  • Sone schrieb:

    a void able schrieb:

    operator new könnte genauso gut char* zurückgeben, weil er ein Byte-Array allokiert.

    In einem anderen Thread habe ich letztens erst gezeigt, dass char nicht einen Byte groß sein muss.

    war das nicht ie Definition von char? Link?



  • Sone schrieb:

    In einem anderen Thread habe ich letztens erst gezeigt, dass char nicht einen Byte groß sein muss.

    Ach, einfach herrlich hier 😋



  • @Sone

    §5.3.3 / 1 schrieb:

    sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1

    Aber meines Wissens muss 1 byte nicht 8 bit gross sein ... oder? Aber dann gibts ja noch uint8_t / int8_t ...



  • otze schrieb:

    Sone schrieb:

    a void able schrieb:

    operator new könnte genauso gut char* zurückgeben, weil er ein Byte-Array allokiert.

    In einem anderen Thread habe ich letztens erst gezeigt, dass char nicht einen Byte groß sein muss.

    war das nicht ie Definition von char? Link?

    Eric Cartman schrieb:

    @Sone

    §5.3.3 / 1 schrieb:

    sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1

    Aber meines Wissens muss 1 byte nicht 8 bit gross sein ... oder? Aber dann gibts ja noch uint8_t / int8_t ...

    Ziehe es zurück, da ging es tatsächlich um die Bitzahl, ein char hat also mindestens 8 Bit, dachte, die Bitzahl des Bytes wäre vom Standard definiert... (Link)
    Ja, char* könnte tatsächlich von den operator new/delete benutzt werden...



  • Sone schrieb:

    Ja, char* könnte tatsächlich von den operator new/delete benutzt werden...

    Also bist du auch der Meinung, dass void* nicht nötig ist?

    Ich ziehe sogar meine Aussage zurück, dass void* für die Definition reinterpret_cast gebraucht wird. Das wird nur benötigt, um Blödsinn mit void* und static-casts zu vermeiden.

    void* kann immer durch reinterpret_cast und char* ersetzt werden und ich würde meinen, das ist immer besser.



  • a void able schrieb:

    void* kann immer durch reinterpret_cast und char* ersetzt werden und ich würde meinen, das ist immer besser.

    Hast du dafür auch irgendeine rationale Begründung?

    Imo sind void* und char* doch sehr verschiedener Natur. Ein char* flüstert einem z.B. ständig ins Ohr: "Mach Zeigerarithmetik mit mir", ein void* schweigt...



  • a void able schrieb:

    Sone schrieb:

    Ja, char* könnte tatsächlich von den operator new/delete benutzt werden...

    Also bist du auch der Meinung, dass void* nicht nötig ist?

    Ich bin unentschieden.



  • dot schrieb:

    Hast du dafür auch irgendeine rationale Begründung?

    char* sagt dir, "ich bin ein Zeiger auf Rohspeicher" und hat irgendeine Länge.

    void* schweigt, egal wie viel du über ihn herausfinden willst. Aber genau das muss irgendwann getan werden, sonst nützt er einem nichts. Entweder ist void* ein Zeiger auf einen Typ, dann sollen Templates benutzt werden, oder void* ist ein Zeiger auf Rohspeicher (Beispiel new/delete), dann soll char* benutzt werden.



  • a void able schrieb:

    void* schweigt, egal wie viel du über ihn herausfinden willst.

    Und wenn ich genau das will? Wieso genau wäre ein char* z.B. im Kontext mit Type Erasure deiner Meinung nach besser als void*?

    Dass operator new void* returned ist wohl historisch bedingt. Dass char* dort sinnvoller wäre, seh ich auch so. Ich würde sogar einen Schritt weiter gehen und meinen, dass das ganze Konzept von new eigentlich flawed ist und die Allokation von Speicher rein Aufgabe einer Library sein sollte. Die Sprache sollte lediglich die Möglichkeit bieten, Objekte in einem gegebenen Speicherbereich zu konstruieren...



  • Zum Template-Bloat mit void* ist mir ein Beispiel eingefallen. Man hat einen Baum und verschiedene Algorithmen darauf (Liste in DFS-Reihenfolge generieren, Liste in BFS-Reihenfolge generieren). Dann könnten die Daten als void* gespeichert werden, weil sie nicht interessieren.

    Aber dann existiert eine noch opakere Lösung:

    template <typename Data>
    struct node {
      node *left, *right;
      /* some internal datas */
    
      Data d;
    };
    
    typedef node<std::aligned_storage<sizeof(char*), std::alignment_of<char*>::value> generic_node
    


  • Das typedef habe ich etwas verhauen:

    typedef node<std::aligned_storage<sizeof(char*), std::alignment_of<char*>::value>::type> generic_node
    

    Aber ich denke, besser wäre ein zentraler generic_pointer:

    // das gleiche wie ein void*, nur dass es nicht einfach zu etwas anderem gecastet werden kann.
    typedef std::aligned_storage<sizeof(char*), std::alignment_of<char*>::value>::type generic_pointer;
    
    // unserer generischer knoten:
    typedef node<generic_pointer> generic_node;
    
    // node lässt sich ganz einfach auch typsicher machen.
    


  • dot schrieb:

    a void able schrieb:

    void* schweigt, egal wie viel du über ihn herausfinden willst.

    Und wenn ich genau das will? Wieso genau wäre ein char* z.B. im Kontext mit Type Erasure deiner Meinung nach besser als void*?

    Hast du denn ein Beispiel wo man void* oder char* braucht?

    Ich denke nämlich, dass es nicht notwendig ist.



  • Der Tobi schrieb:

    void-Pointer kann man sehr wohl in C++ brauchen...

    Zeig mir ein sinnvolles Beispiel für void* (OHNE eine Bibliotheksfunktion zu benutzen, die das fordert), wo man nicht genauso gut mit Templates arbeiten kann.

    Aehm was ist denn das fuer ein Quatsch? Was wenn ich Bibliotheken in C++ schreibe, die in C verwendet werden? Fuer die ganze Interoperabilitaet, abstrakte Datentypen, ... ist void* noetig.


Anmelden zum Antworten