container-typ als template parameter
-
hi leute
wie funktioniert es das ich ne list oder einen vector als template parameter uebergebe ? also den container-typ an sich
sowas:
template<typename CONTAINER, class T> class myclass { typedef CONTAINER<wrapper<T> > container; // wrapper is ne klasse die nur intern verwendet wird };gibts da ne moeglichkeit ?
Meep Meep
-
Prinzipiell geht das so:
template <template<class> class Container> class myclass { Container<int> container; };Wenn du std::vector verwenden willst, musst du allerdings beachten, dass dieser zwei Template-Argumente entgegennimmt.
template <template<class, class> class Container> class myclass { Container<int, std::allocator<int> > container; };BTW: Man darf zwar schreiben
template<typename,typename>class Container, aber das letzteclassmuss einclassbleiben. Frag mich nicht warum.
-
templatetemplatetemplate schrieb:
Wenn du std::vector verwenden willst, musst du allerdings beachten, dass dieser zwei Template-Argumente entgegennimmt.
Oder drei, oder vier. Garantiert ist IIRC nur, dass die ersten beiden Parameter Elementtyp und Allokator sind, Implementierungen dürfen aber noch zusätzliche Parameter definieren - durften sie AFAIK zumindest im alten Standard.
Davon abgesehen wird mit den zwei Parametern z.B. das std::Set diskriminiert, das auf jeden Fall drei Parameter hat (Key, Comparator, Allokator)templatetemplatetemplate schrieb:
aber das letzte
classmuss einclassbleiben. Frag mich nicht warum.Weil der Container eine Klasse(/struct) sein muss, die Templateparameter können sowohl Klassen als auch andere Typen sein.
@Meepmeep: was willst du erreichen?
-
Die beiden folgenden Klassen Templates sind doch äquivalent (typename / class spielt keine Rolle), oder?
template <typename A> class B {};template <class A> class B {};
-
Ja.
-
pumuckl schrieb:
templatetemplatetemplate schrieb:
Wenn du std::vector verwenden willst, musst du allerdings beachten, dass dieser zwei Template-Argumente entgegennimmt.
Oder drei, oder vier. Garantiert ist IIRC nur, dass die ersten beiden Parameter Elementtyp und Allokator sind, Implementierungen dürfen aber noch zusätzliche Parameter definieren - durften sie AFAIK zumindest im alten Standard.
Das war noch nie erlaubt. Sofern kern Bedarf besteht, mit veralteten, fehlerhaften Compilern/Standardbibliotheken zu arbeiten, muss auf diese Problematik keine Rücksicht genommen werden.
template <typename C> struct wrapped_container; template <template <typename, typename> class TT, typename T, typename A> struct wrapped_container<TT<T, A>> { // sanity checks typedef TT<T, A> C; static_assert(std::is_same<T, typename C::value_type>::value); static_assert(std::is_same<T, typename A::value_type>::value); static_assert(std::is_same<A, typename C::allocator_type>::value); typedef TT<wrapped<T>, typename A::template rebind<wrapped<T>>::other> type; }; template <typename T, std::size_t N> struct wrapped_container<std::array<T, N>> { typedef std::array<wrapped<T>, N> type; }; template <typename Container> class myclass { typedef typename wrapped_container<C>::type container_type; container_type container; };lässt sich belieb auf andere Container erweitern, wenn man ggf. entsprechende Wrapper für KeyComp, Hash etc. bereitstellt.
-
hi
@camper
koenntest du mir erklaeren was genau du da gemacht hast ? ich glaub meine template kenntnisse sind eingerostet bzw. nicht gut genug.@pumuckl
ich bau mir zur zeit eine kleine bibliothek zur verwaltung von knotenpunkten die aehnlich wie ein dateisystem mehrere ebenen haben koennen. jeh nach anwendungsfall soll sie intern mit einem vektor bzw. mit einer liste arbeiten.wenn ich nun jedoch deine multimap verwenden moechte hab ich natuerlich das problem mit der anzahl der templateparameter. was mir derzeit egal ist.
@camper
koennte ich nach deinem konstrukt auch eine multimap verwenden ?Meep Meep
-
Meep Meep @ Balkonien schrieb:
@camper
koenntest du mir erklaeren was genau du da gemacht hast ? ich glaub meine template kenntnisse sind eingerostet bzw. nicht gut genug.Ich habe erst mal dein Template-Argument T entfernt, das ist redudant, wenn ein anderer Templateparamter einen Container mit diesem Value-typ beshreiben soll. Ansonst ist das eine einfache Angelegenheit, falls der Container eine Instanz eines Templates mit zwei Typparametern (bei Standardcontainern wären das vector, deque, list, forward_list) ist, wird die erste Spezialisierung genommen. Ein paar zusätzlich Checks sind nur dafür da, offensichtliche Nicht-Container abzufangen, um eine klarere Fehlermeldung zu erhalten.
Meep Meep @ Balkonien schrieb:
@camper
koennte ich nach deinem konstrukt auch eine multimap verwenden ?Klar. Indem eine entsprechende Spezialisierung geschrieben wirde. Zu beachten ist hierbei, dass ggf. das Compare-argument modifiziert werden muss. Das hängt davon ab, was gewrapped werden soll (Der Key oder der Valuetyp oder beides - nicht gewrapped werden kann allerdings das resultierende pair).
z.B.template <template <typename, typename, typename, typename> class TT, typename Key, typename T, typename Comp, typename A> // map, multimap struct ordered_wrapped_container4 { struct new_comp : Comp { bool operator()(const wrapped<Key>& lhs, const wrapped<Key>& rhs) const { return Comp::operator()( unwrap( lhs ), unwrap( rhs ) ); } }; typedef TT<wrapped<Key>, T, new_comp, typename A::template rebind<std::pair<const wrapped<Key>, T>>::other> type; }; template <template <typename, typename, typename, typename> class TT, typename Key, typename Hash, typename Pred, typename A> // unordered_set, unordered_multiset struct unordered_wrapped_container4; // todo template <template <typename, typename, typename, typename> class TT, typename A, typename B, typename C, typename D> // 4 Typargumente: erwischt map, multimap, unordered_set, unordered_multiset struct wrapped_container<TT<A, B, C, D>> : std::conditional<std::is_same<A, typename TT<A, B, C, D>::value_type>::value, unordered_wrapped_container4<TT, A, B, C, D>, ordered_wrapped_container4<TT, A, B, C, D>>::type {};