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 interne au compilateur


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    mai 2007
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : mai 2007
    Messages : 155
    Points : 119
    Points
    119
    Par défaut Erreur interne au compilateur
    Bonjour,

    Voici le code que je compile. Il s'agît d'une simplification d'un truc plus gros :
    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
    //template <class T>
    struct Test {
        template <unsigned _Vb, typename d=void>
        static constexpr unsigned U=
                /*Test<T>::*/U<_Vb-1,d>+2;
    };
     
    //template< class T>
    template <typename p>
    constexpr unsigned Test/*<T>*/::U<0,p> = 5;
     
    int main ()
    {
        enum class test { Debut,A=Debut,B,Fin };
        Test/*<test>*/ testDef;
    }
    Première question : Si je retire tous les commentaires j'obtiens une erreur interne du compilateur ci-après citée (j'utilise QTCreator 4.10/QT5.13.1/MinGW 7.3.0 64b). Ca me l'a également fait en 32b. Quelqu'un pourrait-il me dire si cette erreur se reproduit également gcc gcc/linux?
    07:44:13: Exécution des étapes pour le projet Orientation...
    07:44:13: Configuration inchangée, étape qmake sautée.
    07:44:13: Débute : "D:\Qt\App\Tools\mingw730_64\bin\mingw32-make.exe" -f Makefile.Debug -j8 debug/Base_def.o
    g++ -c -fno-keep-inline-dllexport -Wa,-mbig-obj -g -Wall -W -Wextra -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../Orientation -I. -I../../../../includes/date-master/include/date -ID:/Qt/App/5.13.0/mingw73_64/include -ID:/Qt/App/5.13.0/mingw73_64/include/QtWidgets -ID:/Qt/App/5.13.0/mingw73_64/include/QtGui -ID:/Qt/App/5.13.0/mingw73_64/include/QtANGLE -ID:/Qt/App/5.13.0/mingw73_64/include/QtCore -Idebug -I. -I\include -ID:/Qt/App/5.13.0/mingw73_64/mkspecs/win32-g++ -o debug/Base_def.o ../Orientation/Base_def.cpp
    ../Orientation/Base_def.cpp:8:29: error: expected ';' before ',' token
    Test<T>::U<_Vb-1,d>+2;
    ^
    ../Orientation/Base_def.cpp: In function 'int main()':
    ../Orientation/Base_def.cpp:18:16: warning: unused variable 'testDef' [-Wunused-variable]
    Test<test> testDef;
    ^~~~~~~
    mingw32-make: *** [Makefile.Debug:292: debug/Base_def.o] Error 1
    07:44:13: Le processus "D:\Qt\App\Tools\mingw730_64\bin\mingw32-make.exe" s'est terminé avec le code 2.
    Erreur lors de la compilation/déploiement du projet Orientation (kit : Desktop Qt 5.13.0 MinGW 64-bit)
    When executing step "Make"
    07:44:13: Temps écoulé : 00:01.

    Deuxième question : Maintenant je remets les commentaires et j'obtiens la suite.
    Ci après la sortie du compilo :
    07:29:36: Exécution des étapes pour le projet Orientation...
    07:29:36: Configuration inchangée, étape qmake sautée.
    07:29:36: Débute : "D:\Qt\App\Tools\mingw730_64\bin\mingw32-make.exe" -f Makefile.Debug -j8 debug/Base_def.o
    g++ -c -fno-keep-inline-dllexport -Wa,-mbig-obj -g -Wall -W -Wextra -fexceptions -mthreads -DUNICODE -D_UNICODE -DWIN32 -DMINGW_HAS_SECURE_API=1 -DQT_DEPRECATED_WARNINGS -DQT_QML_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_NEEDS_QMAIN -I../Orientation -I. -I../../../../includes/date-master/include/date -ID:/Qt/App/5.13.0/mingw73_64/include -ID:/Qt/App/5.13.0/mingw73_64/include/QtWidgets -ID:/Qt/App/5.13.0/mingw73_64/include/QtGui -ID:/Qt/App/5.13.0/mingw73_64/include/QtANGLE -ID:/Qt/App/5.13.0/mingw73_64/include/QtCore -Idebug -I. -I\include -ID:/Qt/App/5.13.0/mingw73_64/mkspecs/win32-g++ -o debug/Base_def.o ../Orientation/Base_def.cpp
    ../Orientation/Base_def.cpp:8:26: error: 'U' was not declared in this scope
    /*Test<T>::*/U<_Vb-1,d>+2;
    ^
    ../Orientation/Base_def.cpp:13:33: error: duplicate initialization of 'Test::U<0, p>'
    constexpr unsigned Test/*<T>*/::U<0,p> = 5;
    ^~~~~~
    ../Orientation/Base_def.cpp:13:33: error: got 1 template parameters for 'constexpr const unsigned int Test::U<_Vb, d>'
    ../Orientation/Base_def.cpp:13:33: error: but 2 required
    ../Orientation/Base_def.cpp: In function 'int main()':
    ../Orientation/Base_def.cpp:18:20: warning: unused variable 'testDef' [-Wunused-variable]
    Test/*<test>*/ testDef;
    ^~~~~~~
    mingw32-make: *** [Makefile.Debug:292: debug/Base_def.o] Error 1
    07:29:37: Le processus "D:\Qt\App\Tools\mingw730_64\bin\mingw32-make.exe" s'est terminé avec le code 2.
    Erreur lors de la compilation/déploiement du projet Orientation (kit : Desktop Qt 5.13.0 MinGW 64-bit)
    When executing step "Make"
    07:29:37: Temps écoulé : 00:01.
    J'en déduis qu'on ne peut déclarer de variable récursivement dans ce cas là (il me dit que U n'existe pas). Là j'ai un peu du mal, car je souhaite créer une forme de liste de valeurs liées entre elles de cette manière. Une possibilité de contourner cela (il faut que ce soit constexpr car l'objectif est d'utiliser les variables obtenues dans des déclarations template)?
    Cordialement,
    Marc

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 267
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 267
    Points : 27 939
    Points
    27 939
    Par défaut
    Salut,
    Si j'ai bien compris, tu voudrais avoir des expressions constantes de manière à associer les valeurs
    • 0 --> 5
    • 1 --> 7
    • ...
    • 10 -->25

    Dans un premier temps, je te proposerais de travailler "simplement" avec des valeurs de type bien défini, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    namespace Details {
    template <unsigned V>
    struct Recursive_impl {
    	static constexpr unsigned result = Recursive_impl<V-1>::result + 2;
    };
    template <>
    struct Recursive_impl<0> {
    	static constexpr unsigned result = 5;
    };
     
    } //namespace Details
    J'ai placé ma structure (dont tu peux changer le nom à ta guise ) dans un espace de noms spécifique, parce que cela ne sera jamais qu'un "détail d'implémentation" du reste de ton problème

    La deuxième définition (template <> struct Recursive_impl<0>) est une spécialisation totale de la structure prévue pour mettre fin à la récursion, en définissant une valeur bien spécifique (que tu peux modifier à ta guise) pour le résultat

    Nous pouvons assez facilement vérifier que ce genre de structure fonctionne avec un code aussi simple que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    int main() {
    	auto result = Details::Recursive_impl<1>::result ;
    	std::cout << result << "\n";
    }
    L'étape suivante sera de s'assurer que nous ayons bel et bien à faire à des valeurs susceptibles d'être considérées comme des valeur numérique entières non signées.
    Nous pourrions donc créer un "convertisseur" sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    namespace Details{
    template <typename T>
    struct Converter_impl {
    	static_assert(std::is_integral<T>::value || std::is_enum<T>::value,
    		"T template parameter should be an integral or an enum type");
    	/* parce qu'il est toujours sympa de connaitre le type*/
    	using value_t = unsigned;
    	template<T V> 
    	static constexpr value_t result = Recursive_impl<static_cast<unsigned>(V)>::result;
    };
    } // namespace Details
    encore une fois, je l'ai placé dans l'espace de noms Details parce que ce sera le plus souvent un détail d'implémentation.

    Le static_assert est là pour s'assurer que nous ayons bel et bien à faire à un type qui pourra être aisément converti en unsigned int. Je l'ai défini de manière très restreinte pour éviter les problèmes de conversions et de perte de précision (par exemple, avec les types réels, tels que float ou double) ... Tu peux, bien sur, adapter cette assertion à tes propres besoins

    Ce qui peut d'avantage te surprendre, c'est que j'ai fait appel à static_cast lors de l'appel à Recursive_impl. Je l'ai placé pour éviter les problèmes liés à l'utilisation de valeurs énumérées issues d'énumérations fortement typées. Sans lui, un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main() {
    	enum class Test {
    		Debut,
    		Fin
    	};
    	auto result = Details::Converter_impl<Test>::result<Test::Fin> ;
    	std::cout << result << "\n";
    }
    (qui permet au passage de m'assureer que la conversion fonctionne) m'aurait normalement envoyé sur les roses sous prétexte que le compilateur ne peut pas convertir Test::Fin en valeur non signée .

    Est ce que cela correspond à peu près à tes besoins ?
    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

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 078
    Points : 27 044
    Points
    27 044
    Billets dans le blog
    2
    Par défaut
    Le code compile sous VS2017, avec ou sans les commentaires.
    Les variables templates sont une nouveauté C++14, es-tu sûr de compiler avec cette version ?
    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
    #include <iostream>
    template <class T>
    struct Test {
    	template <unsigned _Vb, typename d = void>
    	static constexpr unsigned U =
    		Test<T>::U<_Vb - 1, d>+2;
    };
     
    template< class T>
    template <typename p>
    constexpr unsigned Test<T>::U<0, p> = 5;
     
    int main()
    {
    	enum class test { Debut, A = Debut, B, Fin };
    	std::cout << Test<test>::U<3>;
    }
    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
    #include <iostream>
    //template <class T>
    struct Test {
    	template <unsigned _Vb, typename d = void>
    	static constexpr unsigned U =
    		/*Test<T>::*/U<_Vb - 1, d>+2;
    };
     
    //template< class T>
    template <typename p>
    constexpr unsigned Test/*<T>*/::U<0, p> = 5;
     
    int main()
    {
    	std::cout << Test::U<3>;
    }
    Affichent 11.
    Si j'y passe une valeur élevée par contre, il ne sait pas faire à cause de la récursivité trop grande.

    Ensuite, je comprends pas du tout où tu veux en venir : tu crées une structure template où tu n'utilises jamais le type template ?
    static constexpr unsigned U = /*Test<T>::*/U<_Vb-1,d>+2; mettre un template avant Test pourrait aider le compilateur à s'y retrouver.
    Perso je préfère une déclaration de ce type
    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>
    template <unsigned _Vb, typename d = void>
    struct Test {
    	template <unsigned V, typename D>
    	struct Internal
    	{
    		static constexpr unsigned U = Internal<V - 1, D>::U + 2;
    	};
    	template<typename D>
    	struct Internal<0, D>
    	{
    		static constexpr unsigned U = 5;
    	};
    	static constexpr unsigned U = Internal<_Vb, d>::U;
    };
     
    int main()
    {
    	std::cout << Test<3>::U;
    }
    Ce code fait la même chose (le template est déplacé de la variable à la structure, si ça dérange tu peux aussi créer une structure intermédiaire interne pour y mettre le template) et est compatible C++11.
    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.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    mai 2007
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : mai 2007
    Messages : 155
    Points : 119
    Points
    119
    Par défaut
    Bonjour, et merci les amis

    @kola01 Oui cela correspond bien. Ta solution me convient d'autant qu'elle va me permettre en l'étendant un peu de résoudre d'autres détails d'implémentation du même style.
    @bousk En fait, j'ai activé C++2a. Cela m'a inspiré une série de tests dans ces conditions, en activant différentes versions de C++ : mon compilateur a bien un souci avec la déclaration telle que je la fais : Elle génère systématiquement une erreur. Soit c'est "erreur : expected ';' before ',' token static constexpr unsigned U = Test<T>::U<_Vb-1ici,d>+2;", soit c'est erreur interne du compilateur.
    Dans tous les cas je crois mon code juste et il y trouve une erreur.
    Je pense que je vais remonter un bug, il va juste falloir que j'essaie avec la dernière version de MinGW avant .
    L'autre 'anomalie' : j'ai même mis des valeurs aberrantes à ma config (faute de frappe une fois), sans que ni qmake ni le compilo n'y trouvent à redire...
    Merci encore pour votre aide

    Cordialement,
    Marc

  5. #5
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    juin 2011
    Messages
    615
    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 : 615
    Points : 2 938
    Points
    2 938
    Par défaut
    Tu peux faire des tests sur différents compilateurs et versions avec https://wandbox.org/ et/ou https://godbolt.org/

    Même avec la dernière version, gcc n'arrive pas à résoudre la récursivité.

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    mai 2007
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : mai 2007
    Messages : 155
    Points : 119
    Points
    119
    Par défaut
    Bonjour,

    @Bousk (j'ai relu ton post ) :
    Ensuite, je comprends pas du tout où tu veux en venir : tu crées une structure template où tu n'utilises jamais le type template ?
    En fait le secret de cette structure c'est la spécialisation de l'interruption de la récursivité. Celle là est liée à mon type template.
    J'en ai créé une par une spécialisation partielle qui correspond à une 'valeur par défaut', mais on pourra changer cela pour tout paramètre du template Test.
    On pourra écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <>
    constexpr unsigned Test<uneClasse>::U<0, p> = 0; // donnera 6 pour Test<uneClasse>::U<3>
    template <>
    constexpr unsigned Test<uneAutreClasse>::U<3, p> = 8; // donnera 14 pour Test<uneAutreClasse>::U<6> et 4 pour Test<uneAutreClasse>::U<2>
    Si on retire le '+2' à l'expression, on obtient un bornage par défaut d'intervalles si on spécialise plusieurs interruptions de récursivité pour le même type template.
    Si j'y passe une valeur élevée par contre, il ne sait pas faire à cause de la récursivité trop grande.
    C'est noté. Je n'y avais pas pensé. Cela dit, dans mon cas ce n'est pas grave, je n'ai pas prévu de faire cela pour des grands intervalles.

    @jo_link_noir Merci pour tes liens. Je vais y faire des tests.
    Même avec la dernière version, gcc n'arrive pas à résoudre la récursivité.
    Même sous linux? (j'ai trouvé un post citant la même erreur interne qui se produisait avec Mingw/gcc et pas Linux/gcc, bien que pas avec le même code)

    Bon je vais signaler un bug, car pour ce que j'en comprends mon code est juste (je n'y fais pas de chose interdite à ma connaissance) et le compilateur signale une erreur sans préciser laquelle (déjà rien que ça le justifie je pense). Sans compter que ça compile en VS2017.

    Je vous remercie tous pour vos interventions !
    @bientôt,
    Marc

  7. #7
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 078
    Points : 27 044
    Points
    27 044
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Teaniel Voir le message
    En fait le secret de cette structure c'est la spécialisation de l'interruption de la récursivité. Celle là est liée à mon type template.
    J'en ai créé une par une spécialisation partielle qui correspond à une 'valeur par défaut', mais on pourra changer cela pour tout paramètre du template Test.
    Et pourquoi ne pas juste créer une constante et mettre le type dedans également ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template <class T, unsigned _Vb, typename d = void>
    static constexpr unsigned U = U<T, _Vb - 1, d>+2;
    template <class T, typename p>
    constexpr unsigned U<T, 0, p> = 5;
     
    #include <iostream>
    int main()
    {
        std::cout << U<void, 3> << std::endl;
        return 0;
    }
    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.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 267
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 267
    Points : 27 939
    Points
    27 939
    Par défaut
    Ah bien alors, peut-être aurais tu intérêt à travailler dans l'autre sens, par exemple en créant un trait de politique basé sur un type bien précis (pour lequel, tu remarquera qu'il y a des prérequis ), tel que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <typename Tag>
    struct TagTrait{
        static constexpr unsigned defaultValue = Tag::defaultValue;
        static constexpr unsigned difference = Tag::difference;
    };
    Tu remarquera la présence de la valeur difference, qui te donnera "un peu plus" de flexibilité dans l'évolution des valeurs (mais que tu peux ignorer si les valeurs doivent toujours évoluer de la même manière )
    avec ta structure récursive qui prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    template <typename Tag, unsigned V>
    struct Recursive{
        static constexpr unsigned value = Recursive<Tag,V-1>::value +TagTrait<Tag>::difference;
    };
    template <typename Tag>
    struct Recursive<Tag, 0>{
        static constexpr unsigned value = TagTrait<Tag>::defaultValue;
    };
    et que tu pourrais utiliser sous une forme proche de
    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
    struct Test{
        enum possibleValues{
            zero,
            one, 
            two,
            three,
        };
        /* parce que le trait de politique cherchera ces deux valeurs bien particulières */
        static constexpr unsigned defaultValue = 10;
        static constexpr unsigned difference = 3;
    };
     
    int main()
    {
    	std::cout << Recursive<Test, Test::one>::value<<"\n";
    }
    Tu remarqueras au passage que j'ai utilisé une enumération simple, pour la simple et bonne raison que les valeurs énumérées ne sont déjà accessibles qu'au travers du nom de la structure

    De même, comme tu peux le remarquer, j'ai défini deux valeurs bien particulières dans cette structure, qui correspondent justement aux valeurs dont les noms sont recherchés par le trait de politique (à savoir :defaultValue et différence).

    Au sujet de ces valeurs particulières, justement, il y a une dernière astuce à savoir: si tu essaye de définir cette structure à l'intérieur d'une fonction, sous une forme qui serait du coup proche de
    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
    int main()
    {
        /* je déplace simplement la structure utilisée dans une fonction */
        struct Test
        {
            enum possibleValues{
                zero,
                one, 
                two,
                three,
            };
            /* parce que le trait de politique cherchera ces deux valeurs bien particulières */
            static constexpr unsigned defaultValue = 10;
            static constexpr unsigned difference = 3;
        };
     
    	std::cout << Recursive<Test, Test::one>::value<<"\n";
    }
    il y a au moins un compilateur (je n'ai testé que Gcc, je ne m'avancerai pas pour les autres ) qui va râler sous prétexte que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    error: local class 'struct main()::Test' shall not have static data member 'constexpr const unsigned int main()::Test::defaultValue' [-fpermissive]
             static constexpr unsigned defaultValue = 10;
    (et il ralera pour la même raison au sujet de différence, d'ailleurs )
    Cela ne veut pas dire que tu ne peux pas définir ta structure dans une fonction bien particulière, parce qu'elle ne sera utile que dans un cas bien particulier. Cela veut juste dire qu'il y a une dernière astuce à garder en tête : les valeurs énumérées sont -- elle aussis -- des constantes de compilation.

    C'est à dire que, si tu définis ces deux valeurs bien particulières directement à l'intérieur de l'énumération, sous une forme qui serait dés lors proche de
    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
    int main()
    {
        /* je déplace simplement la structure utilisée dans une fonction */
        struct Test
        {
            enum possibleValues{
                zero,
                one, 
                two,
                three,
            /* parce que le trait de politique cherchera ces deux valeurs bien particulières */
                defaultValue = 10,
                difference = 3,
            };
        };
     
    	std::cout << Recursive<Test, Test::one>::value<<"\n";
    }
    le compilateur (du moins, Gcc, je ne m'avancerai pas pour les autres) n'y verra plus la moindre objection

    PS : je me demande d'ailleurs si c'est Gcc qui est "trop stricte" sur ce coup là, ou si c'est un problème dans l'énoncé de la norme, car je ne vois pas vraiment pourquoi le compilateur accepte l'un, mais pas l'autre ... Quelqu'un aurait-il une idée à ce sujet
    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

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    mai 2007
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : mai 2007
    Messages : 155
    Points : 119
    Points
    119
    Par défaut
    Bonjour à vous,

    Depuis mon dernier post je suis allé sur https://wandbox.org (Un grand merci à @jo_link_noir). Après un certain nombre d'essais et pas mal de tours sur moi-même, j'ai fini par trouver un code qui fonctionne:
    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
    // This file is a "Hello, world!" in C++ language by GCC for wandbox.
    #include <iostream>
    #include <cstdlib>
     
    template <class T>
    struct Test {
        template <unsigned _Vb, typename b=void>
        static constexpr const unsigned U = Test<T>:: template U<_Vb-1,b>+2;
     
    };
     
    template< class T>
    template <typename b>
    constexpr auto Test<T>::U<0,b> = 5;
     
    int main ()
    {
        enum class test { Debut,A=Debut,B,Fin };
        Test<test> testDef;
        std::cout << testDef.U<3>;
    }
    Le résultat est (bien sur) 11. Et ça compile sur toutes les versions de gcc que j'ai essayées. Le secret c'est la spécification template avant U<_Vb-1,b> (lol sinon le compilo comprend '<' comme le signe inférieur, allez savoir pourquoi!) et constexpr auto devant la déclaration spécialisée.
    Rammené sur mon QTCreator avec MinGW, je retrouve la même erreur interne. C'est donc bien un souci avec MinGW sous QT.
    Je vais voir si je trouve un kit de compilation pour QT utilisant la version la plus récente de MinGW en espérant que ça fonctionne, sinon je suis bon pour signaler un bug finalement.

    Cordialement,
    Marc

    P.S. Sur aucun des sites de test, je n'ai trouvé MinGW. C'est vrai que je ne connais pas grand chose aux différentes versions des compilos, mais il me semble que c'est GCC compilé pour Windows, ce qui expliquerait l'absence de référence à MinGW sur ces sites. Alors pourquoi cette différence?

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 267
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 267
    Points : 27 939
    Points
    27 939
    Par défaut
    En fait, MinGW est le portage de Gcc sous windows.

    De toute évidence, wandbox tourne sous linux, vu qu'il ne propose aucun des compilateurs existant sous windows. Il ne faut pas chercher plus loin

    Par contre, d'après les tests que j'ai fait sur ton propre code avec wandbox, il semblerait qu'il faille utiliser au minimum la version 8.2.0 de Gcc (ou supérieure) pour qu'il soit accepté. C'est peut-être là que réside tout le problème de MinGW, car, à l'heure actuelle, l'outil d'installation de MinGW-w64 permet -- au mieux -- d'obtenir la version 8.1.0 de Gcc.

    C'est dommage, parce qu'il semblerait que MSYS2 fournisse déjà la version 9 de Gcc avec MinGW au travers de son système pacman, alors que je viens de vérifier sur le site de MinGW et la version du dernier build "officiel" est bel et bien la version 8.1.0 de Gcc

    C'est d'autant plus dommage que Qt, par exemple, a pour politique de ne supporter que les builds officiels de MinGW-w64 pour fournir ses binaires précompilé, et qu'il faut impérativement utiliser une version de Gcc utilisant les threads posix et supportant seh comme exception handler pour arriver à compiler soi-même Qt

    Enfin, je viens de vérifier vite fait, il semblerait que les autres distributions de MinGW soient elles-aussi largement à la traine:
    1. nuwen ne semble pas avoir fait de mise à jour depuis Gcc-8.2
    2. TDM n'a quant à lui plus rien fait depuis Gcc-5.1

    Au final, la meilleure solutions semblerait être de compiler soi-même une version "récente" de Gcc, mais c'est un processus qui prend un temps bête
    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

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    mai 2007
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France, Moselle (Lorraine)

    Informations forums :
    Inscription : mai 2007
    Messages : 155
    Points : 119
    Points
    119
    Par défaut
    Eh ben merci pour tes informations
    J'ai remarqué que le head du gcc est la version 10... Donc en effet, MinGW est 'un peu' en retard...
    Je me demande finalement si je n'aurais pas intérêt à m'installer un linux pour le dev, en attendant que le portage soit réalisé.
    En effet je ne me sens pas trop pour compiler GCC, puis créer un kit de dev QT.
    D'autant qu'avec QT, je n'aurais pas trop de mal à porter mon appli sous Win ensuite (quitte à faire une cross-compile au besoin).
    Merci encore pour ton aide.
    Cordialement,
    Marc

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 078
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 078
    Points : 27 044
    Points
    27 044
    Billets dans le blog
    2
    Par défaut
    Tu peux rester sous Windows et utiliser WSL.
    https://code.visualstudio.com/docs/cpp/config-wsl
    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.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 04/06/2010, 11h37
  2. Erreur interne compilateur visual basic
    Par freerider74 dans le forum Visual Studio
    Réponses: 0
    Dernier message: 15/03/2010, 09h26
  3. Réponses: 26
    Dernier message: 28/01/2010, 12h53
  4. Fonction template, erreur interne du compilateur
    Par Emiler dans le forum Langage
    Réponses: 9
    Dernier message: 08/04/2009, 12h14
  5. [BOOST] erreur interne du compilateur
    Par venomelektro dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 15/04/2006, 18h08

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