Je dois effacer des éléments de différents conteneurs stl et boost par un itérateur. Parfois, j'ai aussi besoin de faire cela avec un reverse_iterator donc je voulais envelopper dans une fonction générique (set).Fonction d'effacement générique
Selon ce: Iterator invalidation rules il devrait surtout être possible.
Ce que je suis arrivé à ce jour est la suivante:
template<class T, bool T_IterReturned = helpers::EraseReturnsIterator<T>::value>
struct EraseImpl
{
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
static iterator erase(list& container, iterator it) {
return container.erase(it);
}
static const_iterator erase(list& container, const_iterator it) {
return container.erase(it);
}
};
template<class T>
struct EraseImpl<T, false>
{
// This one gets used for e.g. std::set whos erase does not return
// an iterator until C++11
typedef typename T::iterator iterator;
typedef typename T::const_iterator const_iterator;
static iterator erase(list& container, iterator it) {
container.erase(it++);
return it;
}
static const_iterator erase(list& container, const_iterator it) {
container.erase(it++);
return it;
}
};
template<typename T>
inline typename T::iterator erase(T& container, typename T::iterator it)
{
return detail::EraseImpl<T>::erase(container, it);
}
template<typename T>
inline typename T::reverse_iterator erase(T& container, typename T::reverse_iterator it)
{
typename T::reverse_iterator tmp = it;
return typename T::reverse_iterator(erase(container, (++tmp).base()));
}
Cela devrait fonctionner pour la plupart des cas, mais par exemple un conteneur de type vectoriel qui ne renvoie pas l'itérateur le casserait. Les ensembles n'invalident pas les autres itérateurs -> ok pour utiliser le prochain itérateur. Pour les vecteurs, je devrais stocker l'itérateur précédent (le cas échéant) et le retourner. Pour un retour à l'itérateur (et similaire) sans cela, cela ne fonctionnera pas du tout. Je ne veux pas implémenter un EraseImpl pour tous les conteneurs connus, par ex. cela m'obligerait à inclure tous les en-têtes que je veux éviter.
Est-ce que je peux pour éviter pour tous spécialisés types? Bien sûr, je peux créer un trait avec une énumération comme {Use_Next, Use_Prev} et le laisser non spécialisé pour les conteneurs invalidant tous les itérateurs. Mais encore une fois: je ne veux pas inclure tous les en-têtes possibles.
Vous n'avez pas besoin d'inclure tous les en-têtes, déclaration avant est suffisant pour les traits. – Jarod42
@ Jarod42: Vous ne pouvez pas transmettre les types de bibliothèque standard. C'est pourquoi il y a un '' spécial. Cependant, c'est le seul en-tête de ce genre. –
MSalters
Je suppose qu'il n'y a pas de solution générale. Comment traiteriez-vous un conteneur qui invalide _all_ itérateurs sur 'erase'? Pas si farfelu; un contenant semblable à un vecteur qui rétrécit peut le faire. (Réallocation à un bloc plus petit) – MSalters