Konstruktor mit template ohne Parameter



  • Hallo,

    habe eine nicht-template-Klasse, deren Konstruktor eine Variable eines Typs erstellen soll, welchen ich als Template angeben will.

    Nun hab ich mir das so gedacht, aber der Compiler streikt.

    struct Test {
      template<class T>
      Test() {
        T* x = new T();
      }
    };
    
    int main() {
      Test obj<int>();  // Error: template-id `obj<int>' in
                        // declaration of primary template
    }
    

    Der volkard kam jetzt mit folgender Idee, welche beim MSVC wohl funktioniert, beim gcc aber nicht wie erwartet abläuft und beim comeau garnicht erst compiliert.

    template<class T>
    struct Type {};
    
    struct Test {
      template<class T>
      Test(Type<T> ) {
        cout << "Konstruktor" << endl;
        T* obj = new T();
      }
    };
    
    int main() {
      Test d(Type<int> );
      // das compiliert der g++-3.0 erstmal.
      // Allerdings erscheint keine Ausgabe auf dem Bildschirm,
      // sprich der Konstruktor wird garnicht aufgerufen.
    }
    

    Das ganze ist nicht so dramatisch, weil ich ja auch eine Template-Klasse draus machen kann. Würde mich aber trotzdem interessieren wo hier das Problem liegt.



  • so gehts:

    struct Test 
    {
    template<class T>
        Test(T) 
        {
            T* x = new T();     
        };
    };
    
    int main(int argc, char* argv[])
    {   
        Test obj(int());
        return 0;
    }
    


  • Der Haken an der Sache ist hier, dass du mit int() erst ein int-Objekt erstellst. Bei int ist das zwar latte, aber bei anderen Klassen kommt das nicht gut.



  • Er wills ja ohne Parameter 🙄



  • class test {
    public:
       template <class T>
       test () {
           T t;
       }
    };
    
    int main () {
       test template t <int> ();
    }
    

    der msvc kanns - glaub ich - sicher nicht.
    der borland auch nicht.

    der comeau kompiliert es anstandslos - gcc?



  • Original erstellt von DrGreenthumb:
    **```cpp
    template<class T>
    struct Type {};

    struct Test {
    template<class T>
    Test(Type<T> ) {
    cout << "Konstruktor" << endl;
    T* obj = new T();
    }
    };

    int main() {
    Test d(Type<int> );
    }

    Probier mal mit Type<int>()



  • class test {
    public:
    template <class T>
    test () {
    T t;
    }
    };

    int main () {
    test template t <int> ();
    }

    Das ist schwachsinn und kein gültiges C++. Da man Konstruktoren nicht explizit aufrufen kann, gibt es auch keine Möglichkeit hier Templateargumente explizit zu spezifizieren.
    Wie kommst du darauf, dass der Comeau das übersetzt?

    Volkards Idee war schon richtig. Nur der Aufruf war falsch:

    template<class T>
    struct Type {};
    
    struct Test {
      template<class T>
      Test(Type<T> ) {
        cout << "Konstruktor" << endl;
        T* obj = new T();
      }
    };
    

    Und der Aufruf:

    int main() {
      Test d(Type<int>());  // man beachte die Klammern. Es wird ein temp. Objekt
                            // vom Typ Type<int> erstellt.
    }
    

    Alternativ:

    struct Test {
      template<class T>
      Test(T*) {
        T* obj = new T();
      }
    };
    int main() {
      Test d((int*) 0);  
    }
    

    [ Dieser Beitrag wurde am 29.03.2003 um 14:26 Uhr von HumeSikkins editiert. ]



  • template<class T>
    struct Type {};
    
    struct Test {
      template<class T>
      Test(Type<T> ) {
        cout << "Konstruktor" << endl;
        T* obj = new T();
      }
    };
    
    int main() {
      Test d(Type<int> );     // ===>
      // das compiliert der g++-3.0 erstmal.
      // Allerdings erscheint keine Ausgabe auf dem Bildschirm,
      // sprich der Konstruktor wird garnicht aufgerufen.
    }
    

    <=== DAS ist für den Compiler die Deklaration einer Funktion, die nicht definiert wird. Daher läßt er sie gleich weg 😉



  • @HumeSikkins: wobei du mit deiner 1. Lösung genau das gleiche hast wie ich in meinem 1. Posting, nur hast du's bißl komplizierter gestaltet 😉



  • Erstmal danke für die Antworten.

    Hab leider nur beim schreiben im Forum (und offenbar auch beim comeau) diese Klammern vergessen. 😞

    In meinen gcc-Tests (g++ 2.95 und 3.0.4) hatte ich's jedoch richtig.

    Also ist es wohl ein Bug im gcc 😕



  • Original erstellt von CodeWalker:
    @HumeSikkins: wobei du mit deiner 1. Lösung genau das gleiche hast wie ich in meinem 1. Posting, nur hast du's bißl komplizierter gestaltet 😉

    Nein, du erzeugst mit
    Test t(int()) einen int. bei

    big { char c[2100]; int y[1200]; }
    
    int main () {
    Test t(big());
    }
    

    kann das zum verhängnis werden. volkard instanziiert kein "big"



  • wetten, daß doch ein BIG instanziert wird? 😉 (falls du wettest: ich setze ein Faß Bier *g*)
    wie HumeSikkins schreibt: beim Aufruf wird wird ein temporäres Objekt erstellt!



  • ja, aber ein temporäres Objekt vom Typ Test<big> und sieh dir mal die def. von Test an:

    template <class T>
    class Test { /*ups, leer*/ };
    

    is ja gar nix drin, was speicher verbraucht 😉



  • Achja, die Alternativ-Lösung mit dem (int*)0 Cast funktioniert auch beim gcc.

    Nuja, ist nur nicht besonders schön. Glaube da mach ich dann doch lieber 'ne Template-Klasse. Schade das man den Konstruktor nicht einfach wie eine Template-Funktion ohne Parameter aufrufen kann.



  • könntest dir ja ne Factory bauen



  • hmmm....stimmt auch wieder. Wer kriegt nun das Bier? 😉

    [ Dieser Beitrag wurde am 29.03.2003 um 15:26 Uhr von CodeWalker editiert. ]


Anmelden zum Antworten