Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C++ Discussion :

probleme avec std::find


Sujet :

C++

  1. #1
    Membre du Club
    probleme avec std::find
    Bonjour à tous,
    voila je viens de voir un peu comment fonctionner les iterators et les lambda et j'ai voulu m'entrainer un peu. Mais voila je coince. Je vous montre mon code:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    #include <iostream>
    #include <vector>
    #include <algorithm>
    class A
    {
     
    public:
    	A(int value = 0): m_value(value) {};
     
    	int m_value;
     
    }; 
     
     
    int main()
    {
     
    	std::vector<A> tab(10);
     
    	(*(tab.begin() + 5)).m_value = 66;
     
     
    	auto it = std::find(tab.begin(), tab.end(), [](A &a){
    		if( a.m_value == 66)
    		{
    			std::cout << "yes" << std::endl;
    			return true;
    		}
    		else
    		{
    			return false;
    		}
    	});
     
    	std::cout <<  it->m_value << std::endl;
     
    	return 0;
    }


    le probleme est lorsque je compile mon code ca me retourne l'erreur :
    /usr/include/c++/8/bits/predefined_ops.h:241:17: error: no match for ‘operator==’ (operand types are ‘A’ and ‘const main()::<lambda(A&)>’)
    { return *__it == _M_value; }
    je ne comprends pas du tout l'erreur qu'il me retourne. Le compilateur me parle de operator== alors que je ne vois aucun problème.

    Merci d'avance pour votre aide

  2. #2
    Membre chevronné
    Bonjour.

    std::find doit pouvoir comparer deux objets, pour cela la classe doit indiquer comment le faire avec l'opérateur ==, qui n'est pas présent dans la classe A (d'où l'erreur).

    Il suffit donc d'implémenter l'opérateur dans A.
    Je fais appel aux esprits de Ritchie, Kernighan, Stroustrup et Alexandrescu
    Donnez moi la force, donnez moi le courage de coder proprement !

    « Ça marche pas » n'est PAS une réponse convenable, merci de détailler le souci en fournissant l’environnement, le code source, les commandes et les messages d'erreur.

    Ce club possède également un chat / clavardage, on y trouve quelques perles entre deux sessions d'entraides.

  3. #3
    Expert éminent sénior
    Citation Envoyé par Daïmanu Voir le message

    Il suffit donc d'implémenter l'opérateur dans A.
    Ou, à tout le moins, pour A...

    Ce serait difficilement applicable dans le cas présent (à moins de définir l'opérateur == comme étant une fonction amie de A), mais une fonction libre dont le prototype ressemble à
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    bool operator == (A const & a, A const & b){
        /* ... */
    }
    fonctionnerait au moins aussi bien que l'opérateur sous forme de fonction membre, et présenterait en outre moins de restrictions
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Membre du Club
    Merci pour vos réponses
    donc je peux trouver des objets uniquement en créant l'opérateur== ? ca me parait moyen comme méthode car une fois l'operator== implémenté, je ne peux plus rien changer, et si je veux trouver des objets avec des caractéristiques différents je dois de nouveau changer l'operator==. il n' y pas moyen de mettre des predikas ou des lambdas ?

  5. #5
    Modérateur

    Bonsoir,

    Tu peux, avec std::find_if.
    Avant de poser votre question : FAQ, Tutoriels et recherche sur le forum
    Une erreur ? Messages d'erreur et avertissements
    "Ça ne marche pas" n'apporte aucune information utile permettant de vous aider. Expliquez clairement votre problème (erreurs entières, résultat souhaité vs obtenu...).
    En essayant continuellement on finit par réussir. Donc: plus ça rate, plus on a de chance que ça marche. - Jacques Rouxel
    L'expérience, c'est le nom que chacun donne à ses erreurs - Oscar Wilde
    Mes extensions FireDVP (Firefox), ChroDVP (Chrome) : suivi des nouveaux messages, boutons/raccourcis et bien plus !

  6. #6
    Membre habitué
    Bonjour,

    J'ai fait les tests et... il s'avère que l'opérateur == n'est pas le seul élément en cause ici.
    Globalement, std::find compare les objets d'un conteneur par rapport à un objet quelconque. Je ne vois pas trop ce que vient faire le lambda ici.

    De mon côté, ce code ne fonctionne pas :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
     
     
    struct Test {
    	Test(int const val=int{}): mValue{val} {};
    	int mValue;
    };
     
    bool operator==(Test const & left, Test const & right) { return left.mValue == right.mValue; }
    bool operator!=(Test const & left, Test const & right) { return !(left==right); }
     
    int main() {
    	std::vector<Test> tab(10, Test{});
     
    	tab[5].mValue = 66;
     
    	auto it{ std::find( tab.begin(), tab.end(), [](Test & obj){ return obj.mValue == 66 ? true : false; }) };
     
    	std::cout << it->mValue << '\n';
     
    	return 0;
     
    }


    Car le compilateur me dit que l'on essaie de comparer un objet de type Test à un objet de type lambda....
    Par contre, si on modifie le std::find par : auto it{ std::find( tab.begin(), tab.end(), Test{66}) };, alors tout roule...

  7. #7
    Modérateur

    Citation Envoyé par BioKore Voir le message
    Globalement, std::find compare les objets d'un conteneur par rapport à un objet quelconque. Je ne vois pas trop ce que vient faire le lambda ici.
    Si la classe utilisée ne possède pas d'opérateur ==, ou que l'on souhaite utiliser un critère de comparaison différent, c'est là qu'elle intervient. Mais pas avec std::find (qui recherche un élément == à l'objet passé en paramètre), avec std::find_if (qui recherche un élément sur lequel le prédicat retourne true).

    En passant return obj.mValue == 66 ? true : false; se simplifie en return obj.mValue == 66; et la lambda ne doit pas modifier les éléments du tableau => [](Test const & obj).
    Et dans un cas « normal » d'utilisation où on ne saura pas si l'élément en question est présent ou non, on commencera par vérifier si it != tab.end() avant de l'utiliser.
    Avant de poser votre question : FAQ, Tutoriels et recherche sur le forum
    Une erreur ? Messages d'erreur et avertissements
    "Ça ne marche pas" n'apporte aucune information utile permettant de vous aider. Expliquez clairement votre problème (erreurs entières, résultat souhaité vs obtenu...).
    En essayant continuellement on finit par réussir. Donc: plus ça rate, plus on a de chance que ça marche. - Jacques Rouxel
    L'expérience, c'est le nom que chacun donne à ses erreurs - Oscar Wilde
    Mes extensions FireDVP (Firefox), ChroDVP (Chrome) : suivi des nouveaux messages, boutons/raccourcis et bien plus !

  8. #8
    Membre habitué
    Citation Envoyé par Winjerome Voir le message
    std::find_if
    Yes ! Effectivement, ça marche mieux comme ça avec les lambda !
    Quant au ternaire, c'est plus pour garder l'idée générale de la fonction initiale qui faisait intervenir un std::cout au milieux; mais d'accord avec toi, c'est plus rapide avec return obj.mValue==66;.

    Bref, dans tous les cas, si on utilise std::find_if avec la lambda proposée, on a effectivement pas besoin des opérateurs ==. Logique mais intéressant à savoir.