IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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 :

erreur de compilation : no matching function for call to from_chars


Sujet :

C++

  1. #1
    Membre confirmé

    Inscrit en
    Octobre 2003
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 209
    Par défaut erreur de compilation : no matching function for call to from_chars
    Bonjour.

    je sèche depuis un moment sur la compilation d'un bout de 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
    #include <algorithm>
    #include <cassert>
    #include <fstream>
    #include <charconv>
    #include <iostream>
    #include <string_view>
     
    #include <iomanip>
    #include <optional>
    #include <system_error>
     
    #include "Matrice.hpp"
     
    ...
     
    void Matrice::charger(std::string const &fichier_source)
    {
      std::ifstream lecture (fichier_source);
      std::string ligne {""};
      int valeur{};
     
      while (std::getline(lecture, ligne))
      {
        char sep {','};
        //std::string::iterator debut {std::begin(ligne)};
        //std::string::iterator fin {std::end(ligne)};
        //std::string::iterator pos_sep {};
        //auto debut {std::begin(ligne)};
        //auto fin {std::end(ligne)};
        auto debut {ligne.begin()};
        auto fin {ligne.end()};
        auto pos_sep {debut};
     
        pos_sep=find_if(debut,fin,sep);
        std::from_chars(debut, pos_sep-1 , m_nb_lignes);
    ...
    J'ai "gratté" autant que j'ai pu cppreference.com mais je n'ai pas trouvé mon erreur.

    À la compilation, il bloque sur l'appel à from_chars.
    C:\Users\1.formation.fr69\Documents\codeblocks\exoZestDeSavoir\Matrice\src\Matrice.cpp|38|error: no matching function for call to
    'from_chars(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, int&)'|
    j'ai ajouté toutes les bibliothèques citées dans les exemple, j'ai essayé d'ajouter 10 en dernier argument pour la base (apparemment, c'est optionnel), même résultat.
    j'ai essayé plein de choses en vain...

    L'un d'entre vous saurait-il m'expliquer où je commets une erreur ?

    j'avis oublié. ci dessous, ma classe Matrice où sont définis m_nb_lignes et m_nb_colonnes.
    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
    #ifndef MATRICE_HPP_INCLUDED
    #define MATRICE_HPP_INCLUDED
     
    #include <vector>
     
    class Matrice
    {
    public:
      // constructeurs
      Matrice()=default;
      Matrice(int nb_lignes, int nb_colonnes);
     
      void charger(std::string const &fichier);
      void afficher ();
     
     
    private:
      int m_nb_lignes {1};
      int m_nb_colonnes {1};
      std::vector<int> m_valeurs {};
    };
     
    #endif // MATRICE_HPP_INCLUDED

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 200
    Billets dans le blog
    4
    Par défaut
    Est-ce que tu compiles bien en c++17 ou supérieur ?
    Si oui, il galère sans doute avec les conversions des itérateurs vers char*, aide le avec &*debut, &*pos_sep
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre confirmé

    Inscrit en
    Octobre 2003
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 209
    Par défaut
    Bonjour Bousk.

    a priori, je suis en c++17.
    J'utilise codeblocks 25.03

    Ta solution fonctionne mais pourquoi faut-il en passer par là ?
    ma syntaxe était-elle juste ou non ?

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 200
    Billets dans le blog
    4
    Par défaut
    Ton code ne compile pas, donc non ta syntaxe est pas bonne
    Les iterators sont pas des char* que la méthode attend
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 628
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 628
    Par défaut
    (Edit : crosspost avec Bousk du à un appel téléphonique)

    Bonjour,

    Citation Envoyé par olivier] Voir le message
    Ta solution fonctionne mais pourquoi faut-il en passer par là ?
    ma syntaxe était-elle juste ou non ?
    Parce que std::from_chars attend explicitement des pointeurs vers des chars ( const char* first, const char* last, … ) mais que string::begin() et string::end() renvoient des itérateurs, donc des objets à part entière et pas des pointeurs natifs.

    Alors certes, ils sont faits pour respecter la même sémantique, notamment au niveau de l'incrémentation ++ et du déréférencement * et donc, lorsque c'est possible, ils bénéficient de conversions implicites. On sait aussi qu'incrémenter successivement l'itérateur renvoyé par .begin() doit aboutir in fine à la même valeur et au même type que celui renvoyé par .end() pour qu'ils puissent être comparés entre eux et former ainsi la condition d'arrêt, comme on le ferait avec des pointeurs ordinaires.

    Mais si *iterateur émule un déréférencement à la position courante et nous renvoie le caractère à la position courante (donc un char), rien ne nous dit en revanche qu'il le fasse sur une chaîne qui soit contiguë en mémoire ni même chargée entièrement, donc rien ne nous dit qu'extraire d'emblée deux pointeurs de nos itérateurs nous garantira qu'ils respecteront le même comportement. On ne sait pas non plus si le caractère qui est renvoyé l'est depuis une chaîne en mémoire (éventuellement celle renvoyée par .c_str() ) ou si son adresse est celle d'une variable statique interne ou d'une xvalue.

  6. #6
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    781
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 781
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    Mais si *iterateur émule un déréférencement à la position courante et nous renvoie le caractère à la position courante (donc un char), rien ne nous dit en revanche qu'il le fasse sur une chaîne qui soit contiguë en mémoire ni même chargée entièrement, donc rien ne nous dit qu'extraire d'emblée deux pointeurs de nos itérateurs nous garantira qu'ils respecteront le même comportement. On ne sait pas non plus si le caractère qui est renvoyé l'est depuis une chaîne en mémoire (éventuellement celle renvoyée par .c_str() ) ou si son adresse est celle d'une variable statique interne ou d'une xvalue.
    Comme le montre son code, le container est un std::string, donc contiguë.

    Concernant cette partie du code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    pos_sep=find_if(debut,fin,sep);
    std::from_chars(debut, pos_sep-1 , m_nb_lignes);
    Le std::find_if n'est pas nécessaire et comme tu ne vérifie pas le résultat de from_chars, cela peut cacher des erreurs de format.

    Par exemple, avec la chaîne "123 456,789", le from_chars va trouver 123, alors que le pos_sep est après 456 qui sera ignoré. Le mieux est de prendre le retour de from_chars pour vérifier la présence du séparateur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    auto result = std::from_chars(&*debut, &*fin, m_nb_lignes);
    if (result.ec != std::errc()) { /* erreur */ }
    if (result.ptr == &*fin || *result.ptr != ',') { /* le séparateur est manquant */ }
    // continuer avec `result.ptr + 1`

  7. #7
    Membre confirmé

    Inscrit en
    Octobre 2003
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 209
    Par défaut
    Eh bé... avec mon niveau, je ne risquais pas de débrouiller ça tout seul!
    Merci de vos explications.

    Ce qui m'inquiète, c'est que, finalement, je n'ai pas compris grand'choses au C++. Pour moi, un itérateur était un pointeur. Je vais re-potasser le sujet.

    Mais du coup, comment fait-on pour utiliser from_char avec un string ?
    Autre question, std::begin(ligne) signifie-t-il la même chose que ligne.begin() ?

    jo_link_noir, l'utilisation find_if ne compilait pas.
    /usr/include/c++/14/bits/predefined_ops.h:318:30: error: expression cannot be used as a function
    Alors j'ai utilisé find.

    Et effectivement, je ne vérifie pas le résultat de from_char. Mais dans un premier temps je voulais déjà essayer de faire fonctionner avec des valeurs correctes.

    En fait, j'essaie de charger une matrice à partir d'un fichier.
    Je me doute bien que je réinvente probablement la roue, mais je voulais tester si j'y parvenais avec mes connaissance actuelles...
    Bon... je vous laisse évaluer la réponse

  8. #8
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 329
    Par défaut
    Citation Envoyé par olivier] Voir le message
    a- Pour moi, un itérateur était un pointeur. Je vais re-potasser le sujet.

    b- Mais du coup, comment fait-on pour utiliser from_char avec un string ?
    c- Autre question, std::begin(ligne) signifie-t-il la même chose que ligne.begin() ?

    d- En fait, j'essaie de charger une matrice à partir d'un fichier.
    a- Tu y es presque. C'est le contraire. Un pointeur peut être (parfois!!!) vu et donc, employé, comme un itérateur.

    b- J'avoue que je m'en sers peu. Ce n'est pas une fonction avec une interface des plus simples. Pour commencer à bidouiller il y a des trucs plus abordables côté interface. Le from_chars je vais m'en servir quand je veux optimiser et avoir un contrôle fin.

    c- oui. La version libre, offre plus de souplesse -- d'aveux d'A. Stepanov, il s'était résolu à ne proposer que la version membre en 94 pour brosser dans le sens du poil l’intelligentsia OO

    d- La lecture de fichiers, c'est vite quelque chose de rébarbatif et pas très passionnant, en particulier avec l'API du C++. La version simple se fera avec des >>, mais si on veut commencer à vérifier combien on a de lignes, combien on a de colonnes dans chaque ligne, s'il y a des entêtes dans un format encore différent, si jamais il y a des commentaires, si jamais il y a des caractères invalides par rapport au format... c'est vite des trucs compliqués à maintenir en pur C++.

    C'est normal que tu puisses te sentir un peu dépassé surtout si tu débutes. Il ne faut pas le prendre personnellement.


    PS: C::B n'est pas un compilateur. Ce qui peut parfois nous intéresser pour ajuster nos réponses, c'est ce que tu utilises en vrai dessous: GCC ou clang, et dans quelle version.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #9
    Membre confirmé

    Inscrit en
    Octobre 2003
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Octobre 2003
    Messages : 209
    Par défaut
    Merci pour ton soutien Luc
    Et encore merci à tous pour vos réponses et explications.

    C'est vrai que repondre "CodeBlocks" pour le compilateur n'était la chose la plus pertinente.
    Le compilateur est GNU GCC et dans les options -std=gnu++17

  10. #10
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 628
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 628
    Par défaut
    Citation Envoyé par jo_link_noir Voir le message
    Comme le montre son code, le container est un std::string, donc contiguë.
    C'est bien vu ! J'étais aussi resté au départ sur l'idée admise de longue date qu'une string est contiguë mais je me suis mis à douter au moment d'écrire mon post car cela faisait très longtemps que je n'avais pas vérifié ce fait. Mais c'est bel et bien indiqué chez cppreference :

    Citation Envoyé par cppreference
    The elements of a basic_string are stored contiguously, that is, for a basic_string s, &*(s.begin() + n) == &*s.begin() + n for any n in [0, s.size()]
    … donc utiliser directement les pointeurs reste valide.


    Citation Envoyé par olivier] Voir le message
    Ce qui m'inquiète, c'est que, finalement, je n'ai pas compris grand'choses au C++.
    C'est pareil pour tout le monde. On pense raisonnablement en faire le tour au départ, ce qui est même vrai quand il s'agit de le circonscrire, mais l'explorer et le maîtriser en profondeur demande toujours beaucoup plus d'investissement qu'estimé.

    Pour moi, un itérateur était un pointeur. Je vais re-potasser le sujet.
    Pas tout-à-fait. Un itérateur peut être un pointeur, mais il s'agit généralement d'un objet dédié au parcours d'une structure de données et qui peut prendre n'importe quelle forme. Comme en plus il est généralement spécifique à cette structure, il est souvent défini comme sous-classe de celle qui la définit et la gère. Par exemple : string et string::iterator.

    Si un itérateur ressemble à un pointeur, c'est parce qu'il est fait pour se comporter de la même façon, pour lui être même éventuellement substitué. Par contre, la seule chose qui est exigible d'un objet itérable est d'être parcouru de façon séquentielle. Les « accès aléatoires » sont facultatifs ici. En conséquence, les seules choses qui sont demandées à un objet pour être considéré comme itérable sont :

    Du coté de la classe-mère:
    • De fournir une fonction-membre .begin() ;
    • De fournir une fonction-membre .end() ;
    • Ces deux fonctions renvoyant chacune un itérateur, positionnés respectivement sur le premier élément du jeu de donnée et juste après le dernier élément.


    Du côté de l'itérateur :
    • De pouvoir être déréférencé pour accéder à l'élément courant. Au besoin en réimplémentant operator * () ;
    • De pouvoir être incrémenté (par post-incrémentation). Au besoin en réimplémentant operator ++ () ;
    • De pouvoir être comparés entre eux avec l'opérateur de différence. Au besoin en réimplémentant operator != () ;
    • Que deux itérateurs positionnés sur le même élément d'un même dataset soit considérés comme égaux (donc que l'opération ci-dessus soit false).


    Par contre, il n'est pas demandé à un itérateur de pouvoir revenir en arrière, ni de sauter plusieurs éléments en une opération, ni de pouvoir être indexé avec [ … ] (rien ne t'empêche de l'implémenter quand même au besoin et si c'est possible).

    En ce sens, tout ceci est déjà automatique nativement avec des pointeurs ordinaires (quand on peut y avoir recours, c'est-à-dire quand toutes les données sont chargées consécutivement en mémoire). Si on demande aux itérateurs d'adopter le même comportement, c'est d'une part pour éviter d'avoir à faire une distinction arbitraire dans le code quand on les utilise, ce qui est en soi une mesure de bon sens, mais également parce que ça devient nécessaire quand on utilise des bibliothèques de template. Les itérateurs qui lui sont passés peuvent alors être indifféremment des pointeurs ordinaires ou des objets composite construits pour l'occasion et il est essentiel que la syntaxe du code reste la même dans tous les cas.

  11. #11
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 329
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 329
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    a- Pas tout-à-fait. Un itérateur peut être un pointeur, mais il s'agit généralement d'un objet dédié au parcours d'une structure de données et qui peut prendre n'importe quelle forme. Comme en plus il est généralement spécifique à cette structure, il est souvent défini comme sous-classe de celle qui la définit et la gère. Par exemple : string et string::iterator.

    Si un itérateur ressemble à un pointeur, c'est parce qu'il est fait pour se comporter de la même façon, pour lui être même éventuellement substitué. Par contre, la seule chose qui est exigible d'un objet itérable est d'être parcouru de façon séquentielle. Les « accès aléatoires » sont facultatifs ici. En conséquence, les seules choses qui sont demandées à un objet pour être considéré comme itérable sont :

    b- Du côté de l'itérateur : [...]
    • De pouvoir être incrémenté (par post-incrémentation). Au besoin en réimplémentant operator ++ ()


    c- Par contre, il n'est pas demandé à un itérateur de pouvoir revenir en arrière, ni de sauter plusieurs éléments en une opération, ni de pouvoir être indexé avec [ … ] (rien ne t'empêche de l'implémenter quand même au besoin et si c'est possible).

    En ce sens, tout ceci est déjà automatique nativement avec des pointeurs ordinaires (quand on peut y avoir recours, c'est-à-dire quand toutes les données sont chargées consécutivement en mémoire)..
    a- Je n'aime vraiment pas dire que l'itérateur peut être un pointeur, car c'est vite trompeur. C'est comme dire qu'un fruit peut être une pomme. Pas forcément faux, mais il y a du bruit inutile dans la formulation.

    C'est exactement le contraire comme je disais: un pointeur, dans une séquence d'objets contigus, sera un cas particulier d'itérateur.

    En revanche les itérateurs ont été conçus comme une généralisation des pointeurs, en repartant de la syntaxe du déréférencement et de l'arithmétique des pointeurs.

    b- Tu m'as mis un doute, je suis allé vérifié, et le concept d'incrémentable englobe post, mais aussi pre-incrémentation.
    - que ce soit aujourd'hui, https://en.cppreference.com/cpp/iterator/incrementable
    - comme dans le désign original des concepts d'itérateurs de 94 (ou du moins ce qui a été normalisé en 98): https://www.jmeiners.com/sgi-stl-doc...dIterator.html

    c- Je ne sais plus comment ça été formalisé dans le big tuto C++ de ZdS. J'aimais bien la page de présentation originale que l'on trouve dans la doc de SGI: https://www.jmeiners.com/sgi-stl-docs/Iterators.html
    Cette taxinomie de concepts permet d'exprimer les contraintes minimales attendues dans l'écriture d'algo générique. D'ailleurs si on lit la doc de choses telles que https://en.cppreference.com/cpp/algorithm/copy on voit immédiatement le type d'itérateur attendu sur chaque paramètre.

    Les pointeurs (dans des séquences itérables) quant à eux cochent toutes les cases: input iterator, output iterator (si pas pointeur vers donnée const), forward iterator, bidirectional iterator, random access iterator, et le tout nouveau contiguous iterator.

    Tu peux passer une paire de pointeurs (au détail de la contrainte séquence d'objets contigus) là où tu attends n'importe quel type d'itérateurs. C'est du polymorphisme paramétrique. On parle aussi de Duck Typing: Ca ressemble à un canards, ça a les pattes palmées, ça fait coin, alors pour notre besoin, c'est que c'est un canard.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 16
    Dernier message: 22/04/2021, 10h26
  2. Réponses: 5
    Dernier message: 17/04/2016, 20h36
  3. Réponses: 7
    Dernier message: 14/03/2014, 21h50
  4. Réponses: 1
    Dernier message: 11/01/2014, 19h57
  5. no matching function for call
    Par pimousse280187 dans le forum Linux
    Réponses: 1
    Dernier message: 06/06/2009, 21h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo