Compile Time Polymorphie



  • Hallo,

    wir haben gerade im Studium die Compile Time Polymorphie durchgenommen. Ich habe es glaub fast verstanden. Jedoch verstehe ich zwei Zeilen nicht. Diese sind jedoch wichtig.

    class BASDevice
    {
    public:
    void send(){ cout << "senden" << endl;}
    };

    class NASDevice
    {
    public:
    void send(){cout<< "hier" << endl;}
    };

    class SASDevice
    {
    public:
    void send();
    };

    void SASDevice::send()
    {
    cout<< "servus" << endl;
    }

    template<int>
    struct DriverChoice; // wieso wird ein int template hier erzeugt?

    template<> struct DriverChoice<-1>
    {
    typedef NASDevice type;
    };

    template<> struct DriverChoice<1>
    {
    typedef SASDevice type;
    };

    template<> struct DriverChoice<0>
    {
    typedef BASDevice type;
    };

    struct driver
    {
    //const int ptrBitsVs32 = 1;
    //enum { ptrBitsVs32 = 1};
    typedef DriverChoice<0>::type type; // was bedeutet diese Zeile genau

    };

    int main(int argc, char *argv[]) {

    SASDevice sas;
    sas.send();
    BASDevice bas;
    bas.send();
    NASDevice nas;
    nas.send();
    driver::type d;
    d.send();
    return 0;
    }

    Danke für eure Hilfe


  • Mod

    Compile Time Polymorphie ist ein etwas schwammiger Begriff, weil man vieles darunter verstehen kann. Was du hier zeigst, ist mal was neues, da es irgendwie recht umständlich ist, um einen einfachen Effekt zu erreichen.

    template<int>
    struct DriverChoice; // wieso wird ein int template hier erzeugt?
    

    Willkür, weil der Autor möchte, dass man später einem int statt des Typen benutzen kann.

    typedef DriverChoice<0>::type type; // was bedeutet diese Zeile genau
    

    Sie führt einen neuen Typenbezeichner namens "type" (lokal in der Klasse Driver) ein, der von nun an anstatt DriverChoice<0>::type benutzt werden kann. Dabei ist DriverChoice<0>::type bereits der typedef von weiter oben, aus der DriverChoice-Spezialisierung für 0, also ein anderer Name für BASDevice .

    Das gleiche Programm geht auch mit weniger Indirektionen, ohne viel von dem Polymorphie-Aspekt zu verlieren:

    template<typename T> struct DriverChoice
    {
      typedef T type;
    };
    
    struct driver
    {
      //const int ptrBitsVs32 = 1;
      //enum { ptrBitsVs32 = 1};
      typedef DriverChoice<BASDevice>::type type; 
    };
    

    Oder noch kürzer:

    struct driver
    {
      //const int ptrBitsVs32 = 1;
      //enum { ptrBitsVs32 = 1};
      typedef BASDevice type; 
    };
    

    Oder die Klasse driver ganz weglassen:

    int main(int argc, char *argv[]) {
      typedef BASDevice driver;
      SASDevice sas;
      sas.send();
      BASDevice bas;
      bas.send();
      NASDevice nas;
      nas.send();
      driver d;
      d.send();
      return 0;
    }
    

    Das ist immer noch identisch zum Ursprungscode und noch genau so flexibel. Denn im Prinzip hat der Autor hier nur ein (umständliches) typedef eingeführt und das dann Polymorphie genannt. Finde ich ein bisschen arm, normalerweise verstehe ich darunter etwas ausgefallernere Techniken. Kommt vielleicht noch dran und dies dient nur der Gewöhnung an etwas komplexere Templates und typedefs.

    Noch etwas wichtiges: Achte bei deinen zukünftigen Beiträgen bitte auf korrekte Nutzung der Codetags, damit dein Code lesbar ist. Wenn du meinen Beitrag zitierst, siehst du, wie ich die Tags gesetzt habe. Die Tags können semi-automatisch mit den Buttons unter dem Editfenster (da wo die Smileys sind) erzeugt werden. Erster Klick -> Anfangstag, zweiter Klick -> Endtag; Klick bei markiertem Text -> Tags drumherum setzen.


  • Mod

    Willkür, weil der Autor möchte, dass man später einem int statt des Typen benutzen kann.

    Int2Type-Idiom



  • Hallo,
    habe nicht den "100" orginalcode gepostet. Der sah so aus:

    struct Driver
    {
        enum { bitsPerVoidPtr = CHAR_BIT*sizeof(void*)};
        enum { ptrBitsVs32 = bitsPerVoidPtr > 32 ? 1:
                             bitsPerVoidPtr > 32 ? 0:
                                                    -1
        };
        typedef DriverChoice<ptrBitsVs32>::type type;
    }
    

    Entdert sich was an der Funktion?


  • Mod

    frankbank schrieb:

    Entdert sich was an der Funktion?

    Ja! Vorher hatte der Programmierer fest eine Zahl eingesetzt, um einen bestimmten Typen zu waehlen. Da haette er auch gleich direkt den Typen waehlen koennen. Nun hingegen ist die Entscheidung abhaengig von einer Compilezeitkonstante (aber keiner "programmierzeit"konstanten!). Somit passt dann auch Arcoths Hinweis besser und der Begriff Compilezeitpolymorphie macht auch auf einmal Sinn fuer diese Art Code.



  • Man hätte sich die ganzen Spezialisierungen auch sparen können und einfach std::conditional evrwenden können:

    struct Driver
    {
        constexpr bool bits = CHAR_BIT*sizeof(void*);
        using type = typename std::conditional<(bits>32), SASDevice, 
                     typename std::conditional<(bits>32), BASDevice,
                                                          NASDevice>::type>::type;
    }
    

    (die Bedingungen machen so keinen Sinn, aber sind halt die, die du gezeigt hast.)



  • s/bool/int/


Log in to reply