SmartPointer is not a template
-
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 SmartPointerMeinst 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;SmartPtrbezeichnet hier einen vollständigen Typen wiestd::unique_ptr<int>. Hat den Vorteil, dass du die Anzahl Template-Parameter des Smart-Pointers nicht vorschreibst. Imunique_ptr-Beispiel könnte man einen Deleter angeben.2. Template-Template-Parameter
template <template <typename> class SmartPtr, typename T> class SmartVector;Hier ist
SmartPtrkein Typ, sondern ein Template, das mit einem Typ-Parameter instanziiert werden kann. Zum Beispiel könnte manstd::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 aufconst Type. - Möglicherweise liegt es am Minimalbeispiel, aber
datasollteprivatesein.
- Du kannst auch nur den Smart-Pointer als Typ-Parameter entgegen nehmen. Den Typen extrahierst du dir mit einer Metafunktion, einem Member-Typedef wie
-
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.
