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 :

Problème de définition.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut Problème de définition.
    Bonjour à tous.

    J'ai un programme assez complexe, dans lequel j'ai une quinzaine d'occasions de vouloir utiliser exit() après avoir affiché un message.

    Voici le code de base pour ce genre de sorties
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (!condition) {
    	cerr << "erreur grave!" << endl;
    	exit(-4);
    }
    Plutôt que d'avoir quinze fois ce genre de choses, j'essaie d'obtenir: if (!condition) leave(-4) << "erreur grave!" << endl;Pour se faire, un peu naïvement, je raiie cerr en mettant l'appel à exit() dans le destructeur.
    Sauf que, ca ne compile pas avec g++ 4.4.5:
    Citation Envoyé par g++ -Wall -Wextra -Werror
    In function ‘int main()’:
    error: no match for ‘operator<<’ in ‘leaver(1) << "salut"’
    Voici mon programme de démonstration:
    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
    #include <iostream>
    #include <cstdlib>
    class leaver {
    private:
    	int flag;
    public:
    	explicit leaver(int i) : flag(i) {}
    	~leaver() {::exit(flag);}
    };
     
    template <typename T>
    leaver& operator<<(leaver& leaver, T const& t) {
    	std::cerr << t;
    	return leaver;
    }
     
    int main() {
    	leaver(1) << "salut"<< std::endl;
    	return 0;
    }
    Quelqu'un a-t-il une suggestion?

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    En fait, je suis juste bouché.
    Ca fait deux bonnes heures que j'essaie d'écrire ceci:
    Je m'explique:

    Puisque leaver est une classe, et leaver(int) son constructeur, leaver(1) crée une valeur de ce type.

    template <typename T> leaver& operator<<(leaver& leaver, T const& t); demande en argument une référence non constante.

    donc, avec leaver(1) << 1;, je tente de donner une valeur (temporaire, donc) à une référence non constante.

    gcc me dit qu'il ne connait pas de template valable, mais il aurai pu être plus gentil.

  3. #3
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Moi je ne comprends pas parceque ce code marche chez moi (VS2012) https://github.com/artofsequence/uti...tilcpp/log.hpp

    Et qu'il est similaire.

    (meme si c'est pas une bonne idee et que je vais m'empresser de le remplacer par boost.log bientot)


    J'ai bien essaye ca sur gcc (http://coliru.stacked-crooked.com/):
    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 <cstdlib>
     
    class leaver {
    private:
        int flag;
    public:
    	explicit leaver(int i) : flag(i) {}
    	~leaver() {::exit(flag);}
     
    template <typename T>
    leaver& operator<<( const T& t) {
        std::cerr << t;
        return *this;
    }
     
     
    };
     
     
     
    int main() {
    	leaver(1) << "salut"<< std::endl;
    	return 0;
    }
    Mais j'obtiens plein d'erreurs, la premiere etant:
    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
     
    + g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp
    main.cpp: In function 'int main()':
    main.cpp:23:22: error: no match for 'operator<<' (operand types are 'leaver' and '<unresolved overloaded function type>')
      leaver(1) << "salut"<< std::endl;
                          ^
    main.cpp:23:22: note: candidates are:
    main.cpp:12:9: note: template<class T> leaver& leaver::operator<<(const T&)
     leaver& operator<<( const T& t) {
             ^
    main.cpp:12:9: note:   template argument deduction/substitution failed:
    main.cpp:23:30: note:   couldn't deduce template parameter 'T'
      leaver(1) << "salut"<< std::endl;
                                  ^
    In file included from /usr/include/c++/4.8/iostream:39:0,

  4. #4
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Citation Envoyé par Klaim Voir le message
    Moi je ne comprends pas parceque ce code marche chez moi (VS2012) https://github.com/artofsequence/uti...tilcpp/log.hpp
    VS2012 peut appeler une fonction qui prend une référence alors qu'on lui donne un temporaire. C'est (à priori) pas standard.

  5. #5
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    VS2012 peut appeler une fonction qui prend une référence alors qu'on lui donne un temporaire. C'est (à priori) pas standard.
    GCC aussi comme je viens de le demontrer...

  6. #6
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Une version amelioree qui fait presque ce que tu veux...

    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
    #include <iostream>
    #include <cstdlib>
     
    class leaver {
    private:
        int flag;
    public:
    	explicit leaver(int i) : flag(i) {}
    	~leaver() 
        {
            std::cerr << std::endl;
            ::exit(flag);
        }
     
    template <typename T>
    leaver& operator<<( T&& t) {
        std::cerr << std::forward<T>(t);
        return *this;
    }
     
    };
     
     
     
    int main() {
    	leaver(1) << "salut";
    	return 0;
    }
    A priori std::endl etant une fonction il faudrait prendre carement un pointeur de fonction avec sa signature pour que passe.



    EDIT> A verifier dans le standard mais il me semble bien que les temporaires ne sont aps const, c'est les acces qu'on a aux temporaires qui ont besoin de l'etre. Voir http://stackoverflow.com/questions/6...does-this-work

  7. #7
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Lorsque je dis «modifier un temporaire» c'est modifier le temporaire lui même (pas une copie). Pour moi, c'est un peu comme si tu essayais de récupérer l'adresse d'un temporaire.

    Oui, mais tu as mis la déclaration dans la classe (les règles changent (?)).
    Si tu le sors et prend une référence sur un leaver; ça ne compile pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename T>
    leaver& operator<<(leaver & l, const T& t) {
        std::cerr << t;
        return l;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    main.cpp: In function ‘int main()’:
    main.cpp:22:12: erreur: no match foroperator<<’ (operand types are ‘leaver’ andconst char [7])
      leaver(1) << "salut\n";
                ^
    main.cpp:22:12: note: candidate is:
    main.cpp:16:9: note: template<class T> leaver& operator<<(leaver&, const T&)
     leaver& operator<<(leaver & l, const T& t) {
             ^
    main.cpp:16:9: note:   template argument deduction/substitution failed:
    main.cpp:22:15: note:   cannot convert ‘leaver(1)(type ‘leaver’) to type ‘leaver&’
      leaver(1) << "salut\n";
                   ^

  8. #8
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour

    Tu essayes de modifier un temporaire.
    Soit tu instancies :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
    	leaver l(1);
    	l << "salut\n";
    	return 0;
    }
    Soit tu passes ton leaver par référence sur membre constant (comme il n'est pas modifié) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template <typename T>
    leaver const & operator<<(leaver const & leaver, T const & t)
    {
    	std::cerr << t;
    	return leaver;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int main()
    {
    	leaver(1) << "salut\n";
    	return 0;
    }
    Pour endl, c'est une fonction qui prend un std::ostream donc je pense qu'il faut que ton leaver hérite d'un std::ostream.

  9. #9
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Ok donc c'est pour ca qu'en fait ma version marche mais pas avec std::endl.
    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 <cstdlib>
     
    class leaver {
    private:
        int flag;
    public:
    	explicit leaver(int i) : flag(i) {}
    	~leaver() {::exit(flag);}
     
    template <typename T>
    leaver& operator<<( const T& t) {
        std::cerr << t;
        return *this;
    }
     
     
    };
     
     
     
    int main() {
    	leaver(1) << "salut\n";
    	return 0;
    }
    Au passage, les temporaires ne sont pas const hein...

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

Discussions similaires

  1. [Système] Problème de définition des variables
    Par SLAM JACK dans le forum Langage
    Réponses: 6
    Dernier message: 29/03/2006, 19h53
  2. [Configuration] Problème sur définition de constante
    Par Yobs dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 4
    Dernier message: 24/03/2006, 11h40
  3. Réponses: 1
    Dernier message: 21/12/2005, 19h08
  4. Réponses: 2
    Dernier message: 17/08/2005, 11h20
  5. Réponses: 22
    Dernier message: 05/07/2005, 00h04

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