Question std :: vector comme argument de la fonction template


Je veux créer une méthode de classe prenant une référence std :: vector comme argument et je veux l'utiliser avec différents types de données.

La fonction devrait ressembler à:

void some_function(const std::vector & vect){ //do something with vector }

et je veux l'utiliser avec par exemple:

std::vector<int> v1;
some_function(v1);
std::vector<string> v2;
some_function(v2);

J'espère que j'ai bien compris. Dois-je créer une méthode de template comme celle-ci:

template<class T>
void some_function(std::vector<T> & vect){}

ou puis-je le faire d'une autre manière? S'il le faut, dites-moi s'il vous plaît comment je peux écrire cette méthode dans une classe.

Merci pour l'aide!


15
2017-09-30 12:30


origine


Réponses:


La bonne façon pour un template fonction d'accepter tout std::vector par const& est:

template<typename T, typename A>
void some_func( std::vector<T,A> const& vec ) {
}

le second argument est le "allocateur", et dans certaines utilisations avancées de std::vector ce ne sera pas le défaut. Si vous acceptez seulement std::vector<T>, votre some_func va rejeter std::vectors avec des allocateurs alternatifs.

Maintenant, il y a d'autres façons d'aborder cette question que je vais énumérer rapidement. Je vais les énumérer en coûts décroissants: ratio avantages - celui ci-dessus est probablement ce que vous voulez, et le suivant est parfois utile, et ensuite je vais me concentrer sur des cas d'ingénierie qui valent rarement la peine d'être considérés (mais pourraient être utiles) dans certains cas en coin).

Vous pourriez accepter un type arbitraire T par T&& puis testez pour déterminer si typename std::remove_reference<T>::type Est une sorte de std::vector. Cela vous permettrait de faire "une transmission parfaite" de la std::vector. Cela vous permettrait également de changer le prédicat que vous utilisez pour tester plus que juste un std::vector: pour la plupart, const& à std::vector probablement juste besoin d'un conteneur arbitraire d'accès aléatoire.

Une façon ridicule serait de faire une fonction en deux étapes. La deuxième étape prend une vue à plage d’accès aléatoire de type effacé (ou simplement une vue de distance si vous n’avez pas besoin d’un accès aléatoire) pour un type fixe T avec SFINAE pour s'assurer que l'objet entrant est compatible, la première étape déduit le type de conteneur du type passé et appelle la deuxième étape dans un contexte SFINAE (auto some_func(...)->decltype(...)).

Comme type d'effacement de std::vector<T> const& à une vue de plage d'accès aléatoire de contigu Ts ne perd pas beaucoup de fonctionnalités, un avantage serait que vous pourriez garantir que le corps de votre fonction est exactement le même pour std::vector<T> const& et pour T[n] et pour std::array<T,n>.

Ce n'est pas un gros avantage, surtout pour le passe-partout requis.

 peut rendre cela beaucoup plus facile, car le SFINAE en plusieurs étapes ci-dessus se réduira en quelques clauses obligatoires.


25
2017-09-30 13:05