Template spezialisierung



  • Ist es irgendwie möglich ein template das 2Parameter hat nur mit dem zweiten Parameter zu spezialisieren?

    Ich würde das gerne nutzen um einer Klasse 2Implementierungen zu ermöglichen und den Benutzer auswählen zu lassen, das soll ca. so aussehen:

    template< typename T, Version version >
    class Base
    {
     public:
      struct Version{};
      static const Version version1;
      static const Version version2;
    };
    
    class Derived : public Base< Derived, Base::version1 >
    {
    };
    

    Und je nachdem ob der zweite Parameter version1 oder version2 ist würde ich gerne eine andere Implementierung verwenden.
    Gibt es da irgendwie nen Trick?

    Zur Not muss ich es halt doch per Präprozessor lösen.



  • Eine Klasse mit zwei möglichen Implementierungen würde ich noch anders gestalten:

    class MyInterface
      {
      public:
      virtual void do_this() = 0;  
      virtual int do_that() = 0;
      virtual ~MyInterface() = 0;
      };
    
    class MyClass : public MyInterface
      {
      private:
      MyInterface * impl;
      public:
      MyClass(MyInterface * implementation) : impl(implementation) {};
      virtual ~MyClass() { delete impl; };
    
      virtual void do_this() { impl->do_this(); }
      virtual int do_that() { return impl->do_tha(); }
      };
    
    class MyImplementation1 : public MyInterface
      {
      // Implementiert MyInterface auf die eine Art
      };  
    
    class MyImplementation2 : public MyInterface
      {
      // Implementiert MyInterface auf die andere Art
      };
    

    Der Einbau im Programm wäre dann ein

    main()
      {
      MyClass mc1(new MyImplementation1);
    MyClass mc2(new MyImplementation2);
      }
    

    Wenn dus unbedingt mit Templates machen musst, gehts so ähnlich (Interface und die Implementationen wie oben):

    template<class Implementation>
    class MyClass
      {
      Implementation* impl;
      public:
      MyClass() : impl(new Implementation) {};
      ~MyClass() { delete impl; };
      //Rest wie oben
      };
    

    Ist in meinen Augen nicht so schön, zumal die erste Version noch die Möglichkeit bietet, die Implementierung mitten im laufenden programm zu wechseln:

    class MyClass
      {
      // alles wie in der ersten Version oben
      public:
      void change_impl(MyInterface* newimpl) 
        { 
        delete impl;
        impl = newimpl;
        }
      };
    
    main()
      {
      MyClass mc1(new MyImplementation1);
      mc1.change_impl(new MyImplementation2);
      }
    


  • Danke 🙂

    Ich will es mit templates machen um polymorphie zu vermeiden an dieser Stelle im Programm.
    Da die eine Implementierung für singlethreaded Programme und die andere für multithreaded Programme ist, müsste man eh neu kompillieren, wenn man sich entschließt umzustellen, von daher ist es egal.



  • User-- schrieb:

    Ist es irgendwie möglich ein template das 2Parameter hat nur mit dem zweiten Parameter zu spezialisieren?

    Aber natürlich, du musst nur aufpassen, weil einige Steinzeit Compiler damit Probleme haben.

    template<typename T, Version version>
    class Base {
      //...
    };
    
    template<typename T>
    class Base<T, version1> {
      //...
    };
    


  • User-- schrieb:

    Da die eine Implementierung für singlethreaded Programme und die andere für multithreaded Programme ist, müsste man eh neu kompillieren, wenn man sich entschließt umzustellen, von daher ist es egal.

    Dann brauchst du garnicht mit Templates oder Polymorphie zu arbeiten. Schließlich taucht bei dir nur eine Klasse auf. Wenn du zur Compilierungszeit entscheiden willst, wie die Klasse implementiert sein soll, dann schreib zu einem Header doch zwei CPP's und linke dann bei der Compilierung des Programmes die richtige von beiden mit ein. So besteht auch nicht mehr das Problem, dass du überall im Quelltext alles von "version1" auf "version2" ändern musst.

    myclass_singlethread.cpp

    #include "myclass.hpp"
    //implementierung für single-threads
    

    myclass_multithread.cpp

    #include "myclass.hpp"
    //implementierung für multi-threads
    
    g++ -o singlethreadprog main.cpp myclass_singlethread.cpp
    g++ -o multithreadprog main.cpp myclass_multithread.cpp
    


  • Kingruedi, das ist ja super (und Steinzeitcompiler werden nicht unterstützt) 🙂

    Pumuckl, das würde gehen, wenn diese Klasse nicht Teil einer Bibliothek wäre, welche nur aus einer großen Datei besteht die zu einem Projekt dazugelinkt wird.


Anmelden zum Antworten