0

Première question sur stackoverflow :) Je suis relativement nouveau en C++, et n'ai jamais utilisé de modèles, alors pardonnez-moi si je fais quelque chose de stupide. J'ai une fonction de modèle qui parcourt une liste et vérifie un élément spécifié d'un type général. De cette façon, je peux spécifier s'il cherche une chaîne, un int, ou autre.La fonction de modèle donne l'erreur "aucune fonction correspondant à l'appel"

template <class T> 
bool inList(T match, std::string list) 
{ 
    int listlen = sizeof(list); 
    for (int i = 0; i <= listlen; i++) { 
     if (list[i] == match) return true; 
     else continue; 
    } 
    return false; 
}; 

Ceci est mon appel à inList(). testvec est un vecteur de chaîne avec quelques éléments, y compris « test »:

if (inList<string>("test", testvec)) 
    cout << "success!"; 
else cout << "fail :("; 

À mon grand désarroi et la confusion, à la compilation, je suis giflé avec l'erreur suivante:

error: no matching function for call to 'inList(const char [5], std::vector<std::basic_string<char> >&)' 

Qu'est-ce que je fais incorrectement? :(

[EDIT] j'oublié de mentionner que la définition du modèle est dans l'espace de noms global. (C'est un programme de test simple pour voir si mon modèle fonctionne, et il n'a pas, semble-t-:()

Répondre

4

En effet, il n'existe aucun moyen de convertir un fichier std :: vector en un fichier std :: string, ce que vous devez faire est abstrait par rapport au concept d'une collection

Vous faites cela pour que les utilisateurs puissent passer Ils peuvent utiliser un tableau, un vecteur, une chaîne de caractères, une liste, une deque ... tant que cela correspond au «concept» d'une collection (en espérant que C++ 1x est livré avec des concepts !). Ils peuvent même utiliser leur propre interne types de collection spécialement optimisés. C'est la beauté des modèles.

Utilisation 11 C++ (fonctionne avec tout type collection, les tableaux primitifs, et des types définis par l'utilisateur):

template<class elem_t, class list_t> 
bool in_list(const elem_t& elem, const list_t& list) { 
    for (const auto& i : list) { 
     if (elem == i) { 
     return true; 
     } 
    } 
    return false; 
} 

EDIT: Il est une extension non standard pour déduire std :: initializer_list comme matrice l'argument, afin de fournir une dérogation explicite:

template<class elem_t> 
bool in_list(const elem_t& elem, std::initializer_list<elem_t> list) { 
    for (const auto& i : list) { 
     if (elem == i) { 
     return true; 
     } 
    } 
    return false; 
} 

Avec cette version, vous pouvez l'appeler comme:

int main() { 
    std::vector<int> a = {1, 2, 3, 4, 5}; 
    std::cout << in_list(3, a) << std::endl; 
    std::string b = "asdfg"; 
    std::cout << in_list('d', b) << std::endl; 
    std::cout << in_list('d', "asdfg") << std::endl; 
    std::cout << in_list(3, {1, 2, 3, 4, 5}) << std::endl; 
    return 0; 
} 

Et pour ceux d'entre nous qui sont encore en C++ 98, cela fonctionnera à la fois pour les chaînes et les vecteurs, et pour certains types définis par l'utilisateur. Cela ne fonctionnera pas avec les tableaux bruts.

template<class elem_t, class list_t> 
bool in_list_98(const elem_t& elem, const list_t& list) { 
    list_t::const_iterator end = list.end(); //prevent recomputation of end each iteration 
    for (list_t::const_iterator i = list.begin(); i < end; ++i) { 
     if (elem == *i) { 
     return true; 
     } 
    } 
    return false; 
} 

Ou, vous pouvez aller style STL:

template<class elem_t, class iterator_t> 
bool in_list_stl(const elem_t& elem, iterator_t begin, iterator_t end) { 
    for (iterator_t i = begin; i < end; ++i) { 
     if (elem == *i) { 
     return true; 
     } 
    } 
    return false; 
} 
//call like std::string s = "asdf"; in_list_stl('s', s.begin(), s.end()); 

Si je fait une erreur, désolé, je n'ai pas mon compilateur en cours d'exécution en ce moment ...

+0

La variété est bonne . La réponse courte est de passer une chaîne à la place d'un vecteur de chaînes l'attendant pour la convertir en chaîne. Il y a techniquement 'includes()' ou 'find()' à cette fin cependant; – chris

+0

Je pense que chris a supprimé son commentaire sur ma question avant de rafraîchir ma page, car elle n'est plus là, puisque ce qu'il a mentionné a résolu mon problème. Je me sens très bête. J'avais 'std :: string' comme argument à' inList() 'parce que je ne savais pas que je pourrais utiliser' std :: vector 'littéralement. J'ai pensé que j'aurais dû utiliser 'std :: string' parce que c'est ce que le vecteur a pris, mais maintenant je me sens stupide en y repensant.** Merci à vous deux pour vos réponses, votre réponse est également utile pour référence future, Robert:) ** – ZeroKnight

+0

Si vous utilisez std :: includes ou std :: find, n'oubliez pas de tester avec end(). in_list (a, b) == [] (const auto & a, const auto & b) {return std :: trouver (b.begin(), b.end(), a)! = b.end(); } - note Je veux dire que lambda est une abstraction, pas un code réel - je sais que nous n'avons pas de lambdas polymorphes. C'est quelque chose que nous devons laisser avec haskell pour le moment. –

Questions connexes