SmartPointer is not a template



  • Ich versuche gerade eine Klasse zu schreiben die sich um einen Vector mit Smartpointer kümmert:

    #ifndef SMARTVECTOR_H_INCLUDED
    #define SMARTVECTOR_H_INCLUDED
    
    #include <memory>
    #include <vector>
    
    template < typename SmartPointer, typename Type >
    class SmartVector
    {
        public:
            void push_back( Type* type );
    
            std::vector < SmartPointer< Type > > data;
    };
    
    template < typename SmartPointer, typename Type >
    void SmartVector< SmartPointer, Type >::push_back( Type* type )
    {
        SmartPointer< Type* > pointer( new Type(type) );
        data.push_back( pointer );
    }
    
    #endif // SMARTVECTOR_H_INCLUDED
    

    Ich bekomme die Fehlermeldung die ich als Titel geschrieben haben.



  • Laut Zeile 13 und 19 ist SmartPointer ein Klassentemplate. Laut Zeile 7 jedoch nur ein "einfacher Typ", da muss statt typename SmartPointer ein

    typename <typename, typename> class SmartPointer
    

    hin.

    Das hilft dir zwar für jetzt, aber vielleicht schaffst du den Rest dann selbst 😉



  • Laut Zeile 13 und 19 ist SmartPointer ein Klassentemplate. Laut Zeile 7 jedoch nur ein "einfacher Typ", da muss statt typename SmartPointer ein

    typename <typename, typename> class SmartPointer
    

    Meinst du das so ?

    template < typename Type, typename <typename, typename> class SmartPointer >
    

    Da bekomme ich ein error:

    expected nested-name-specifier before ‘<’ token|
    


  • Sorry, vertippsel und keine Ahnung wieso ich auf zwei Templateparameter komme. Wohl nen Einfluss eines anderen Threads 🙂 (cooky ist schuld)

    template < template <typename> class SmartPointer, typename Type >
    


  • Du musst überlegen, was du willst.

    1. Typ-Template-Parameter

    template <class SmartPtr, typename T>
    class SmartVector;
    

    SmartPtr bezeichnet hier einen vollständigen Typen wie std::unique_ptr<int> . Hat den Vorteil, dass du die Anzahl Template-Parameter des Smart-Pointers nicht vorschreibst. Im unique_ptr -Beispiel könnte man einen Deleter angeben.

    2. Template-Template-Parameter

    template <template <typename> class SmartPtr, typename T>
    class SmartVector;
    

    Hier ist SmartPtr kein Typ, sondern ein Template, das mit einem Typ-Parameter instanziiert werden kann. Zum Beispiel könnte man std::unique_ptr übergeben. Du vermeidest auf diese Weise die doppelte Angabe des Typs, jedoch schränkst du die Wahl des Smart-Pointers ein.

    Weitere Anmerkungen:

    • Du kannst auch nur den Smart-Pointer als Typ-Parameter entgegen nehmen. Den Typen extrahierst du dir mit einer Metafunktion, einem Member-Typedef wie value_type , oder implizit durch Templates bzw. C++11-Typinferenz.
    • Den Header <memory> brauchst du nicht. Wenn Benutzer ihn brauchen, sollen sie ihn selbst inkludieren.
    • Die Signatur von push_back() ist äusserst unintuitiv. Wenn der Parameter ein Zeiger auf nicht-konstante Objekte ist, gehe ich davon aus, dass er direkt in den Smart-Pointer eingefügt wird. Was du aber machst, ist eine Kopie davon -- angebrachter wäre in diesem Fall eine Referenz auf const Type .
    • Möglicherweise liegt es am Minimalbeispiel, aber data sollte private sein.


  • Ich hatte eigentlich die Idee eine Klasse zu schreiben die mir mir so etwas ersparrt:

    #include <memory>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
        std::vector < std::unique_ptr< int > > foo;
        //Das soll die Klasse selber machen und ich muss nur push_back und denn Datentype eingeben
        std::unique_ptr< int > bar( new int(12) );
        foo.push_back( std::move( bar ) );
    }
    

    Warum sollte ich denn vector private machen? ich will ja nur eine push_back funktion ohne std::unique_ptr. So sollte es aussehen:

    SmartVector< std::unique_ptr< int > > foo;
    foo.push_back( new int( 12 ) );
    


  • Dann brauchst du gar keine Klasse. Eine freie Funktion genügt völlig.

    template <typename T>
    void push_back_smartptr(std::vector<T>& container, T* newValue)
    {
        container.push_back( std::unique_ptr<T>(newValue) );
    }
    


  • Vielleicht sind Boosts Pointer Container für dich ganz interessant.



  • Äh...wo du doch schon C++11 verwendest...

    #include <memory>
    #include <vector>
    
    int main() {
      std::vector<std::unique_ptr<int>> foo;
    
      foo.emplace_back(new int(12));
    }
    


  • seldon schrieb:

    Äh...wo du doch schon C++11 verwendest...

    #include <memory>
    #include <vector>
     
    int main() {
      std::vector<std::unique_ptr<int>> foo;
    
      foo.emplace_back(new int(12));
    }
    

    Habe ich auch daran gedacht zu schreiben, macht aber wohl in diesem Fall kein Unterschied. Oder siehst du das anders? Abgesehen davon, dass wir uns trotzdem nur noch die emplace-Funktionen angewöhnen sollten, weil sie alles können was push_back auch kann* und dazu auch perfect forwarding beherrschen.

    * bis auf aggregat initialisierung



  • OK, sorry. Hier macht das natürlich einen wesentlichen Unterschied. Meine Gedanken waren noch bei Nexus's Funktion. Da ist es unwesentlich. Aiaiaia, heute denke ich mehr an die Vergangenheit als ordentlich hinzuschauen.



  • seldon schrieb:

    Äh...wo du doch schon C++11 verwendest...

    #include <memory>
    #include <vector>
     
    int main() {
      std::vector<std::unique_ptr<int>> foo;
    
      foo.emplace_back(new int(12));
    }
    

    Ich bin quasi ein Fan von emplace. Aber in diesem Fall ist die Verwendung von emplace -- meiner Meinung nach -- nicht ausnahmesicher. Das Problem ist hier, dass im Fehlerfall von emplace_back gar kein unique_ptr erzeugt wird. Die Verantwortung zur Verwaltung einer Resource sollte frühstmöglich an ein schlaues Objekt abgegeben werden. Das passiert hier relativ spät bis gar nicht.

    Die Sache mit der Ausnahmesicherheit macht make_unique dann auch so interessant, dass wir es wohl noch für C++14 bekommen *wunschdenk*.



  • krümelkacker schrieb:

    Die Verantwortung zur Verwaltung einer Resource sollte frühstmöglich an ein schlaues Objekt abgegeben werden.

    👍

    http://herbsutter.com/gotw/_102/


Anmelden zum Antworten