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 :

boost + gcc = bug sur les tests d'existence de fonction libre.


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut boost + gcc = bug sur les tests d'existence de fonction libre.
    Bonjour à tous,

    J'utilise boost 1.57 pour tester l'existence d'un opérateur << avec mingw 4.7 et je remarque un comportement plutôt perturbant avec le code ci-dessous.

    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 <boost/type_traits/has_operator.hpp>
    #include <ostream>
    #include <iostream>
     
    #define BUG
     
    class Test
    {
     
    };
     
    #ifdef BUG
    bool debBoost = boost::has_left_shift<std::ostream&, const Test&, std::ostream&>::value;
    #endif
     
    std::ostream& operator<<(std::ostream&, const Test&);
     
    bool endBoost = boost::has_left_shift<std::ostream&,const Test&, std::ostream&>::value;
     
    int main()
    {
        #ifdef BUG
        std::cout<<"debBoost = "<<debBoost<<"\n";
        #endif
        std::cout<<"endBoost = "<<endBoost<<"\n";
    }
    Globalement, si j'active BUG, debBoost = endBoost = 0, sinon, endBoost =1. Est-ce un comportement normal ?

    Ensuite, j'ai voulu tester une solution maison (juste pour ce cas). La voici :

    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 <ostream>
    #include <iostream>
    #include <type_traits>
     
    class Test
    {
     
    };
     
    struct delay
    {
        template<typename T>
        delay(const T&);
    };
     
    std::false_type operator<<(std::ostream&, delay);
     
    bool deb = !std::is_same<decltype(std::declval<std::ostream&>() << std::declval<const Test&>()), std::false_type>::value;
     
    std::ostream& operator<<(std::ostream&, const Test&);
     
    bool end = !std::is_same<decltype(std::declval<std::ostream&>() << std::declval<const Test&>()), std::false_type>::value;
     
    int main()
    {
        std::cout<<"deb = "<<deb<<"\n";
        std::cout<<"end = "<<end<<"\n";
    }
    Et je n'ai pas eu de soucis...

    Ce problème est-il uniquement chez moi ?

    Finalement, après un troisième test, le problème ne vient pas de boost puisque j'obtiens les même résultats que boost.

    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
    39
    #include <ostream>
    #include <iostream>
    #include <type_traits>
     
    #define BUG
    class Test
    {
     
    };
     
    struct delay
    {
        template<typename T>
        delay(const T&);
    };
     
    std::false_type operator<<(std::ostream&, delay);
     
    template<typename T>
    struct Has
    {
        static constexpr bool value = !std::is_same<decltype(std::declval<std::ostream&>() << std::declval<const T&>()), std::false_type>::value;
    };
     
    #ifdef BUG
    bool deb = Has<Test>::value;
    #endif
     
    std::ostream& operator<<(std::ostream&, const Test&);
     
    bool end = Has<Test>::value;
     
    int main()
    {
        #ifdef BUG
        std::cout<<"deb = "<<deb<<"\n";
        #endif
        std::cout<<"end = "<<end<<"\n";
    }
    Je suppose que tout ce ci est normal... Est-il possible de faire pour que la valeur soit évaluée lorsqu'elle est demandée et non à la première demande ?



    [EDIT] Je n'ai testé le deuxième code qu'après avoir commencé à éditer le message, et je ne pensais pas que le problème venait de boost (je pensais que ma solution allait échouer elle aussi). Quelqu'un pourrait-il déplacer la conversation dans le forum dédié à boost ?

    [EDIT2] Finalement, ce n'est pas lié à boost

  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
    a priori, c'est parce que tu instancies une template, puis la réinvoque.

    à la première instance, il trouve faux, du coup, à la seconde invocation, c'est toujours faux.
    Même si entre temps, la cause du faux a changé.

  3. #3
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    a priori, c'est parce que tu instancies une template, puis la réinvoque.

    à la première instance, il trouve faux, du coup, à la seconde invocation, c'est toujours faux.
    Même si entre temps, la cause du faux a changé.
    Oui, c'est ce que j'avais déduis du troisième test... Mais peut-on l'éviter ? Est-ce un comportement lié au compilateur utilisé ?

  4. #4
    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
    C'est lié à la nature même des templates.
    Une instance précise d'une template est matérialisée à sa première invocation.
    Concrètement, le code correspondant est "écrit et compilé" à ce moment-là.

    Une seconde invocation se contentera d'utiliser le même code.

  5. #5
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Ok, mais est-ce garanti que les résultats soient les mêmes avec tous les compilateurs ?

    Notamment, si je fait un #define HAS_SHIFT_LEFT(C) !std::is-same... (voir deuxième solution), puis-je être certain que la valeur est recalculée à chaque fois ?
    Y a t-il une solution plus "propre" qu'un #define pour obtenir le même résultat ?

    [EDIT] Je vais profiter de ce thread pour demander s'il existe un trick pour contourner les problèmes de templates dans le test d'existence de fonction (j'imagine que non, mais on ne sait jamais...). Imaginons que j'ai template<typename T> auto serialize(const T&) mais que cette fonction ne compile pas pour toutes les classes. Est-il possible de définir un constexpr bool hasSerialize<C> ?

  6. #6
    Membre émérite
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    [EDIT] Je vais profiter de ce thread pour demander s'il existe un trick pour contourner les problèmes de templates dans le test d'existence de fonction (j'imagine que non, mais on ne sait jamais...).
    J'ai vaguement l'impression que ma crainte face à ton précédent thread se confirme. Tu vas essayer de tout faire contrôler à ton compilateur (y compris ce qu'il contrôle déjà) à coup de template qui ne feront qu'une chose : Complexifier ton code.

    Imaginons que j'ai template<typename T> auto serialize(const T&) mais que cette fonction ne compile pas pour toutes les classes
    Ben tu laisses le compilateur afficher un message d'erreur... Un utilisateur de ton système pourra toujours faire une adaptation pour que ça deviennent possible sur sa classe.

    Tu comptes mettre des genres de "concept" sur chaque erreur de programmation possible quand bien même le compilateur effectue déjà un contrôle?

Discussions similaires

  1. Tutoriel sur les tests, bugs & rock'n'roll
    Par Francis Walter dans le forum Architecture
    Réponses: 2
    Dernier message: 26/10/2014, 02h28
  2. Information sur les tests réseaux
    Par KasTelo dans le forum Hardware
    Réponses: 6
    Dernier message: 28/07/2006, 19h46
  3. [VBS]Bug sur les boucles for.
    Par méphistopheles dans le forum VBScript
    Réponses: 7
    Dernier message: 24/03/2006, 22h17
  4. Réponses: 4
    Dernier message: 25/04/2005, 15h48

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