Template Erklärung



  • Hi,

    ich habe folgenden Codeschnipsel bei Stackoverflow gefunden.
    Mir ist klar was dieser bezweckt.
    Allerdings ist in z. B. der Forward-Declaration der Proxy struct ein Konstrukt,
    das ich so noch nicht gesehen habe.

    Warum ist dort zweimal der T-Templateparameter?
    Ist der zweite Parameter überhaupt ein "Parameter" oder nur eine zusätzliche "Typangabe"?
    Ändere ich das zweite T in z. B. F funktioniert es nicht mehr.
    Wieviele Template-Parameter hat die struct jetzt eigentlich?
    Wenn ich mir den Aufruf unten anschaue würde ich sagen "zwei" obwohl
    es ja mit T, R, ...args (das Pack zähle ich mal als einen Parameter), Funktionspointer "vier" sind.
    Ich denke das ist eine spezielle Syntax wegen dem Funktionspointer?

    Wer kann erklären was es damit auf sich hat?
    Und warum darf der Funktionspointer nach dem Parameter Pack Template-Parameter stehen?
    Ich dachte ein Parameter Pack muss immer das letzte Argument sein?

    template <typename T, T> struct proxy;
    
    template <typename T, typename R, typename ...Args, R (T::*mf)(Args...)>
    struct proxy<R (T::*)(Args...), mf>
    {
    	static R call(T& obj, Args&&... args)
    	{
    		return (obj.*mf)(std::forward<Args>(args)...);
    	}
    };
    
    hello obj;
    proxy<void(hello::*)(), &hello::b>::call(obj);
    


  • Die proxy-Struktur hat 2 Template-Parameter:

    • typename T: ein Typ
    • T: ein Wert vom Typ T

    In der Template-Spezialisierung werden zwar 4 Template-Parameter für die Deklaration angegeben, die beiden in der Mitte dienen aber nur als Typ-Deklaration für den letzten Template-Parameter R (T::*mf)(Args...), damit klar ist, was R und Args dort bedeuten.
    Die eigentliche Template-Spezialisierung verwendet ja nur zwei Parameter: <R (T::*)(Args...), mf>, wobei mf dabei ein konkreter Funktionszeiger des Typs R (T::*)(Args...) ist (was man ja auch im Aufruf in der letzten Code-Zeile sieht).



  • Nochmal eine Frage. Warum funktioniert die "call" Funktion nicht mit Funktion b(mit int Pointer) aber mit a(int)?

    error: rvalue reference to type 'int *' cannot bind to lvalue of type 'int *'
    
    class hello
    {
    public:
            void a(int arg)
    	{
    		std::cout << "a" << std::endl;
    	}
    	void b(int* arg)
    	{
    		std::cout << "b" << std::endl;
    	}
    };
    
    int main()
    {
            int i = 42;
    	int* pi = new int(42);
    	hello obj;
            proxy<void(hello::*)(int), &hello::a>::call(obj, i);
    	proxy<void(hello::*)(int*), &hello::b>::call(obj, pi);
            return 0;
    }
    


  • Verwende dafür std::move:

    proxy<void(hello::*)(int*), &hello::b>::call(obj, std::move(pi));
    


  • Solange Du keine riesen Interfaces für multinationale Konzerne einwickelst, solltest Du davon Abstand nehmen Templates einzusetzen. Besser ist es die vorhandenen zu verwenden, selbst erstellte Template-Codes lassen sich in Zukunft ggf. nur noch Mühselig -Compilieren geschweige denn das man selber noch weiß was vor sich geht, insbesondere wenn der Gebrauch von Templates überhand annahm , lenzlich sind es auch nur Namens -Ersetze'r, die aus Äpfel Birnen machen.



  • @KahnSoft das ist eine Außenseitermeinung (von einem Spamaccount?)



  • This post is deleted!


  • @KahnSoft sagte in Template Erklärung:

    Solange Du keine riesen Interfaces für multinationale Konzerne einwickelst, solltest Du davon Abstand nehmen Templates einzusetzen. Besser ist es die vorhandenen zu verwenden, selbst erstellte Template-Codes lassen sich in Zukunft ggf. nur noch Mühselig -Compilieren geschweige denn das man selber noch weiß was vor sich geht, insbesondere wenn der Gebrauch von Templates überhand annahm , lenzlich sind es auch nur Namens -Ersetze'r, die aus Äpfel Birnen machen.

    Das sehe ich anders. Ich setze templates gelegentlich ein, weil sie für ein bestimmtes Problem die eleganteste beste Lösung darstellen. Funktionstemplates setze ich sogar noch etwas häufiger ein als Klassentemplates. Mit multinationalen Konzernen hat das gar nix zu tun. Templates sind manchmal die beste Lösung. Also warum nicht verwenden? Warum sollten die "mühselig zu kompilieren" sein? Die Compilezeit ist etwas höher, aber das ist aus meiner Sicht auch schon der einzige Nachteil. Zumal in Zeiten in denen man auf beliebig vielen Cores parallel kompilieren kann...



  • @It0101 Kann man natürlich machen, nach einem halben Jahrhundert programmieren sieht man alles jedoch etwas anders als der Durchschnitt. Und jeder alte versucht natürlich seine Eindrücke weiter zu reichen. Oft sind es die Bauernregeln die an Gewicht erhalten bleiben.


Log in to reply