3 votes

Définition d'une fonction afin qu'elle puisse accepter soit une liste soit un vecteur

J'ai une fonction qui doit recevoir soit une std::list soit un std::vector d'objets MyClass * et effectuer tout un tas de traitements en fonction de ce qui se trouve à l'intérieur. Je ne veux pas dupliquer le corps de la fonction.

J'ai juste besoin d'utiliser ces objets pour les parcourir et effectuer quelques vérifications en lecture seule.

Je pensais passer directement les itérateurs .begin() et .end(), mais cela ne semble pas très joli du tout.

Y a-t-il un moyen meilleur de contourner cela, actuellement j'ai la solution suivante (qui crée une autre liste à partir du vecteur passé, ce qui n'est guère idéal non plus).

void process(std::list input)
{
    //Beaucoup de traitements
    BOOST_FOREACH(MyClass* itMyClass, input)
    {
        //quelques vérifications, création d'une nouvelle liste basée sur les vérifications      
    }
    //Beaucoup de traitements
}
void process(std::vector input)
{
    process(std::list(input.begin(), input.end()));
}

EDIT:

Il semble que beaucoup de personnes suggèrent finalement d'utiliser begin() et end(), j'ai réussi à le faire fonctionner de manière similaire à l'exemple ci-dessous. Merci pour votre aide.

//Celui-ci est privé
template 
void process(Iterator begin, Iterator end)
{
    //Beaucoup de traitements
    for (; begin != end; ++begin) 
    {
        //quelques vérifications, création d'une nouvelle liste basée sur les vérifications
    }
    //Beaucoup de traitements
}
void process(std::list input)
{
    process(input.begin(), input.end());
}
void process(std::vector input)
{
    process(input.begin(), input.end());
}

4voto

Kilian Points 125

Vous pouvez utiliser un modèle de fonction pour cela :

template
void process(ListOrVector const& input) {
    //votre code
}

//Vous pouvez également utiliser un paramètre de modèle de modèle
template> class ListOrVector>
void process(ListOrVector const& input) { ... }

Notez que je prends ListOrVector par référence constante (le const &). Cela évitera une copie.

EDIT

J'ai corrigé le deuxième exemple. Le class avant ListOrVector manquait et l'allocateur est std::allocator par défaut.

0voto

El Profesor Points 10915

Tout comme les fonctions ordinaires, les modèles de fonctions peuvent également être surchargés, de sorte que vous puissiez avoir le meilleur des deux mondes : un algorithme basé sur les itérateurs pour plus de flexibilité et un autre basé sur le conteneur pour plus de simplicité d'utilisation.

De cette manière, vous pouvez utiliser la surcharge basée sur les itérateurs pour traiter une sous-zone d'un conteneur et celle basée sur le conteneur pour traiter tous les éléments d'un conteneur.


process(first, last)

Je vous conseille tout d'abord de définir un modèle de fonction process() qui prend une paire d'itérateurs pour la séquence d'éléments que vous souhaitez traiter :

template
void process(Iterator begin, Iterator end) {
   for (auto it = begin; it != end; ++it) {
      // ...
   }
}

Il s'agit d'un algorithme basé sur les itérateurs (c'est-à-dire, il prend une paire d'itérateurs) et correspond à la même approche que suivent les algorithmes de la STL.


process(container)

Ensuite, je définirais une autre fonction modèle process() qui surcharge la première. Cette surcharge prend un conteneur et appelle la version basée sur les itérateurs de process() sur les éléments du conteneur passé :

template
void process(Container const& c) {
   process(std::begin(c), std::end(c));
}

Il s'agit d'un algorithme basé sur le conteneur, car il prend un conteneur.


De cette façon, vous pouvez utiliser un algorithme basé sur le conteneur au lieu d'un basé sur les itérateurs :

std::vector vec{1, 2, 3};
std::list lst{1, 2, 3};
std::array arr{1, 2, 3};
int carr[] = {1, 2, 3};

process(vec);
process(lst);
process(arr);
process(carr);

Cet algorithme est dissocié des conteneurs à traiter (par exemple, il fonctionne même avec des tableaux de style C, comme vous pouvez le voir), mais vous l'appelez directement sur un conteneur au lieu de passer des itérateurs.

Vous pouvez toujours appeler la surcharge de process() qui prend une paire d'itérateurs au lieu d'un conteneur lorsque vous ne voulez pas traiter tous les éléments d'un conteneur, mais seulement une sous-zone des éléments qu'il contient.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X