Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Résolu] fonction membre auto

en séparant déclaration et implémentation

Sujet résolu
    31 mars 2021 à 18:19:03

    Bonjour à tous,

    J'ai une classe Number qui possède un std::string en variable membre.

    J'ai doté la classe "d'accesseurs aux fonctions du membre value_" (la classe ne sert pas qu'à ça, mais ce n'est - je pense - pas important) tels que begin(), cbegin(), crbegin() etc..

    La classe est séparée en deux fichiers; number.hpp pour les déclarations et implémentations template, et number.cpp pour les autres implémentations.

    Voici le main :

    #include "number.hpp"
    #include <iostream>
    
    int main() {
        std::cout << *(Number("255").begin()) << std::endl;
        // devrait renvoyer '2' ?
        return 0;
    }

    Mais VS me sort une erreur :

    > C3779 : 'Number::begin()': a function that returns 'auto' cannot be used before it is defined

    J'ai compris (au moins je crois) le message d'erreur, il n'arrive pas à déterminer le type de retour de la méthode, parce qu'il ne trouve pas la définition.

    Cependant, je suis sûr que number.cpp est bien inclus au projet car d'autres fonctions implémentées dans ce fichier sont utilisables.

    Que puis-je faire pour y remédier ?

    -
    Edité par Chi_Iroh 1 avril 2021 à 19:04:13

    • Partager sur Facebook
    • Partager sur Twitter
      31 mars 2021 à 18:44:56

      Il faudrait voir comment tu as implémenté tes fonctions.
      • Partager sur Facebook
      • Partager sur Twitter
        31 mars 2021 à 20:16:39

        Bonjour,

        Le compilateur n'a pas à rechercher la définition pour trouver le type dans la déclaration (en aucun cas il ne fait une recherche dans une autre unité de compilation donc dans un autre fichier cpp). Si ta déclaration ne fournit pas l'information sur le type tu ne peux pas l'utiliser; C'est l'erreur que tu as.

        Avoir une déclaration qui ne fournit pas le type exact, ça n'est possible que si l'utilisateur "voit" la définition. C'est donc très particulier.

        Il te faut donc indiquer le type dès la déclaration.

        • Partager sur Facebook
        • Partager sur Twitter

        En recherche d'emploi.

          1 avril 2021 à 13:07:07

          Merci pour vos réponses.

          Voici le code minimal (les autres fonctions sont inutiles pour ce sujet) :

          // number.hpp
          
          class Number {
              std::string value_{ "0" };
          
              public:
              auto begin() const;
          };
          // number.cpp
          auto Number::begin() const {
              return value_.begin();
          }

          @Dalfab, donc je devrais indiquer le type comme ceci ?

          decltype(value_.begin()) begin() const;


          Parce que je pense que réécrire le type de std::string::begin() ne serait pas très propre ?

          EDIT :

          Cela ne fonctionne toujours pas, même avec decltype(std::string::begin()), où le compilateur (j'ai utilisé GCC 10) me dit :

          number.hpp:44:31: error: cannot call member function 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::iterator std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::begin() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::iterator = std::__cxx11::basic_string<char>::iterator]' without object
             44 |   decltype(std::string::begin()) begin() const;
                |                               ^
          number.hpp:44:31: error: cannot call member function 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::iterator std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::begin() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::iterator = std::__cxx11::basic_string<char>::iterator]' without object
          Source.cpp: In function 'int main()':
          Source.cpp:6:16: error: invalid type argument of unary '*' (have 'int')
              6 |   std::cout << *Number("255").begin();
                |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~


          Suis-je obligé d'écrire le type à la main ?

          -
          Edité par Chi_Iroh 1 avril 2021 à 13:26:15

          • Partager sur Facebook
          • Partager sur Twitter
            1 avril 2021 à 16:21:28

            ce n'est pas begin() qu'il faut utiliser dans decltype(), mais cbegin() puisque le membre value est à ce moment constant.

            À ce niveau, autant utiliser std::string::const_iterator qui est plus parlant que la version avec decltype().

            • Partager sur Facebook
            • Partager sur Twitter
              1 avril 2021 à 19:03:54

              Merci @jo_link_noir, tout fonctionne :

              // number.hpp
              
              std::string::iterator begin();
              
              std::string::const_iterator begin() const;
              
              // number.cpp
              
              std::string::iterator math::Number::begin() {
              	return value_.begin();
              }
              
              std::string::const_iterator math::Number::begin() const {
              	return value_.begin();
              }

              Bonne continuation à vous.

              • Partager sur Facebook
              • Partager sur Twitter

              [Résolu] fonction membre auto

              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
              • Editeur
              • Markdown