Template methode erzwingen



  • Ich suche nach einer Möglichkeit eine Methode in einem Template zu erzwingen.

    In der Unit in der das Template verwendet wird, wird eine Templatemethode nicht aufgerufen. Folglich wird diese nicht erstellt. Später wird diese Unit jedoch wo anderst verwendet, wo diese Methode aufgerufen werden soll.

    Im Augenblick schaut die "Lösung" so aus:

    if(true==false)
        this->display(""); // Zwangserzeugung der Methode
    

    Gibt es dem Standard nach eine elegantere Möglichkeit die erzeugung zu erzwingen ?



  • denke damit:

    template<> class MyClass::display<char*>();

    ps: guten morgen 🙂



  • Guten Morgen (wobei ich noch seit gestern wach bin :o( )

    IMHO macht die Spezialisierung keinen Sinn. Ich möchte ja T verwenden und wüsste nicht wie ich das auf T spezialisieren soll, zumal ich ja sicherlich die Spezialisierung auch aufrufen müsste damit diese angelegt wird ?!

    Hier mal die gekürzte Klasse:

    template <class T> public ref class formhelper
    {
    public:
    	T^		frm;
    	T^		display(System::String ^ filter);
    
    	formhelper()
    	{
    		//if(true==false)
    		//	this->display("");
    
    	}
    };
    


  • Knuddlbaer schrieb:

    In der Unit in der das Template verwendet wird, wird eine Templatemethode nicht aufgerufen. Folglich wird diese nicht erstellt. Später wird diese Unit jedoch wo anderst verwendet, wo diese Methode aufgerufen werden soll.

    Und das ist der Grund, warum man die Implementierung von Templates direkt im Header unterbringen sollte - da hat der Compiler den Quelltext überall dort zur Hand, wo er gebraucht wird.

    (übrigens könnte der Compiler dein "if(true==false)..." auch rausoptimieren ;))

    PS: Dein Code sieht übrigens eher nach C++/CLI aus als nach reinem C++ - und ich bin mir nicht sicher, ob im managed Umfeld andere Regeln gelten.



  • Ja, das ganze ist managed, hab es hier rein gestellt, da templates IMHO eher was mit standard zu tun haben.

    Ich erläutere mal kurz das Problem:

    Eine große Applikation hat den VS2005 Formdesigner ausgereitzt (geht nicht mehr, zerstückelt quellcode). Nach langer Diskussion mit dem Support und vielen experimenten und hotfixes später, entschloss ich mich das ganze auf viele DLLs zu verteilen. Das Design ist nicht ideal und die Zeit ist durch 3 Monate ergebnislose Diskussion verstrichen und der Zeitdruck zu hoch um große Designänderungen zu machen.

    Nun gibt es viele Formen im Projekt, die sich zuvor alle kannten und der Compiler bei verwendung von display natürlich auch die implementierung erzeugt hat.

    Nun gibt es z.B. die Form RechnungDetail die in der gesammten Rechnung.dll die Methode display verwendet. Also ist in der DLL nirgends RechnungDetails::display vorhanden.

    In der Hauptform soll später mittels Events und blablabla RechungDetail::display aufgerufen werden. Die Methode gibt es nun aber nicht
    in der dll , weil durch das Template ja nur das implementiert wird, was auch wirklich verwendet wird.

    Hierfür suche ich eine Lösung und hoffte das der Standard da vllt. was bietet. (Wenn es da keine Lösung für gibt die ein Implementieren eines Templatemembers garantiert, könntet Ihr mich ins C++/CLI verschieben ? Eventuell gibt es dann Compilerspezifisch eine Lösung).

    (Das Template wurde verwendet, weil ich im Managed keine Mehrfachvererbung habe und die Funktionalität, von der ich lieber geerbt hätte, nun als Delegate einsetze. Es gibt mehrere Methoden die für jede Form gültig ist und einige Garantien für den Betrieb herstellen).



  • Wenn du eine explizite Spezialisierung angibst, wird die afaik komplett angelegt. Ansonsten dürfte es nur recht einschränkend möglich sein, Templates mit DLLs einzusetzen (der Compiler kann nur eigene Spezialisierungen anlegen, wenn er den Quellcode kennt - und wenn der in deiner DLL verborgen ist, kannst du nur mit den Spezialisierungen arbeiten, die dort schon angelegt wurden).



  • Hallo,
    warum nicht einfach das Naheliegenste, nämliche eine "explicit template instantiation"-Anweisung, verwenden?

    template <class T>
    struct Foo {
    void f() {}
    };
    
    // erzwingt die Instanziierung *aller* Methoden von Foo<int>
    template class Foo<int>;
    
    // erzwingt die Instanziierung von f für Foo<char*>
    template void Foo<char*>::f();
    

    Oder du verwendest Eric Nieblers "Instantiator":
    http://www.geocities.com/eric_niebler/instantiator.html



  • Das Problem ist, das ich den Typ für den das Template verwendet wird nicht kenne.

    Ein

    template class Foo<T>;
    

    wird wohl nicht gehen 🤡

    Danke für den Link, *schon am lesen bin*



  • @Knuddlbaer
    Wenn du die Instanziierung einer Methode erzwingen willst, sobald das Template irgendwie instanziiert wird, musst du einen kleinen Trick anwenden: gut funktioniert z.B. das hier:

    template <class T>
    struct Foo {
      Foo() {
          // Force instantiation of f1
          void (Foo::*p)() = &Foo::f1;
          (void)p;
       }
      void f1() { ... }
      void f2() { ... }
      void f3() { ... }
    
    };
    

    Das setzt natürlich voraus, dass du eine Instanz deines Templates erzeugst. In diesem Fall ist aber garantiert, dass f1 ebenfalls instanziiert wird.



  • Daaaanke schöööööön



  • Hmm...

    klappt leider nicht, weil das ganze "Managed" ist und dort die Adresse nicht.

    Fehler 1 error C2843: 'DMSKV::formhelper<T>': Die Adresse eines nicht statischen Datenmembers oder einer Methode eines verwalteten Typs kann nicht übernommen werden

    Da ich nicht davon ausgehe, das der Standard noch ein Trick auf lager hat, könnte mich jemand nach C++/CLI verschieben ?

    Vllt. kann man ja den Trick doch anwenden 🤡

    Danke!



  • Knuddlbaer schrieb:

    Hmm...

    klappt leider nicht, weil das ganze "Managed" ist und dort die Adresse nicht.

    Fehler 1 error C2843: 'DMSKV::formhelper<T>': Die Adresse eines nicht statischen Datenmembers oder einer Methode eines verwalteten Typs kann nicht übernommen werden

    Ich kenne mich nicht wirklich mit C++/CLI aus, aber hier könnte ein Delegate helfen:

    template <class T> public ref class formhelper
    {
    public:
        T^        frm;
    		T^        display(System::String ^ filter);
    
        formhelper() {
    			ForceInst^ x = gcnew ForceInst(this, &formhelper::display);   
        }
    private:
    	delegate T^ ForceInst(System::String^ str);
    };
    

    Eine Variante, die zumindest auf jedem VC funktioniert: display einfach virtual machen. Virtuelle Methoden instanziiert der VC immer sobald ein Objekt erzeugt wird.



  • Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum C++/CLI mit .NET verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Prima, das geht 🤡

    Oh man, jetzt wo ich mal nachgelesen hab, was delegate treibt, ist die Lösung sowas von naheliegend gewesen.....

    Danke Dir !


Log in to reply