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 :

Détermination automatique de paramètres de patron : erreur interne du compilateur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 104
    Par défaut Détermination automatique de paramètres de patron : erreur interne du compilateur
    Bonjour,

    Dans le code situé à la fin de ce message, j'ai une classe 'exec' template avec plusieurs paramètres. Le dernier paramètre est l'adresse d'une méthode, dont le type est déterminé par les autres paramètres. La fonction 'maker' de ce code doit, étant donné une méthode d'une classe, retourner une instance de 'exec' où les types auront été déterminés automatiquement.

    Lorsque je compile cet exemple, avec g++ 4.3 ou 4.4, j'ai l'erreur suivante :
    test_f_temp.cpp: In member function ‘void exec<C, R, A1, A2, method_name>::caller::run(base_object&) const [with C = T1, R = int, A1 = int, A2 = double, R (C::* method_name)(A1, A2) = method_name]’:
    test_f_temp.cpp:30: internal compiler error: in expand_expr_real_1, at expr.c:7314
    Please submit a full bug report,
    with preprocessed source if appropriate.
    See <file:///usr/share/doc/gcc-4.4/README.Bugs> for instructions.
    Je ne vois pas ce qui le perturbe dans le code, alors je cherche une alternative que mon compilateur apprécierait plus. Remarquez, de plus, que le problème ne se pose que pour l'appel à 'maker'. La partie concernant 'c0' dans le main() passe très bien.

    Pourriez-vous me dire si vous voyez un problème dans le code*? si ça compile bien avec votre compilateur et si vous voyez une alternative*?

    Cordialement,

    Julien

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    #include <iostream>
     
    class base_object
    {
    public:
      virtual ~base_object() { }
    }; // class base_object
     
    // classe mère pour la classe exec::caller ci-dessous
    class base_caller
    {
    public:
      virtual void run(base_object& i) const = 0;
    }; // class base_caller
     
    // Cette classe définit une dérivée de base_caller pour appeler une méthode de
    // la classe C, de type de retour R et dont les paramètres sont de type A1, ...,
    // An. Une instance de ce caller est crée.
    template< typename C, typename R, typename A1, typename A2,
              R (C::*method_name)(A1, A2) >
    class exec
    {
    public:
      typedef R (C::*method_type)(A1, A2);
     
    public:
      class caller:
        public base_caller
      {
      public:
        virtual void run(base_object& i) const
        {
          C& inst( dynamic_cast<C&>(i) );
          const method_type m(method_name);
          (inst.*m)(1, 0);
        }
      }; // class caller
     
      static caller instance;
    }; // class exec
     
    template< typename C, typename R, typename A1, typename A2,
              R (C::*method_name)(A1, A2) >
    typename exec<C, R, A1, A2, method_name>::caller
    exec<C, R, A1, A2, method_name>::instance;
     
    // méthode pour trouver l'instance de exec<>::instance qui convient en fonction
    // de la fonction à appeler.
    template<typename C, typename R, typename A1, typename A2>
    base_caller* maker( R (C::*method_name)(A1, A2) )
    {
      return &exec<C, R, A1, A2, method_name>::instance;
    }
     
    // petit exemple
    class T1:
      public base_object
    {
    public:
      int test( int a, double b )
      { std::cout << "T1" << std::endl; return 0; }
    };
     
    int main()
    {
      T1 t1;
     
      base_caller* c0 = &exec<T1, int, int, double, &T1::test>::instance;
      c0->run(t1);
     
      base_caller* c1 = maker( &T1::test );
      c1->run(t1);
     
      return 0;
    }

  2. #2
    Membre chevronné Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Par défaut
    Déjà, il te dit quand même que c'est une erreur du compilateur >< !

    Ensuite, j'ai l'impression qu'il a du mal a résoudre "method_name". Ca me parait normal puisque ce n'est pas un paramètre template. Est-ce que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    template<typename C, typename R, typename A1, typename A2, 
            R (C::*method_name)(A1, A2)>
    base_caller* maker( R (C::*method_name)(A1, A2) )
    {
      return &exec<C, R, A1, A2, method_name>::instance;
    }
    ne parait pas plus logique ? A mes yeux oui, mais je peux me tromper !

  3. #3
    screetch
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    1>e:\test\main.cc(52) : error C2971: 'exec' : template parameter 'method_name' : 'method_name' : a local variable cannot be used as a non-type argument
    1>        e:\test\main.cc(22) : see declaration of 'exec'
    1>        e:\test\main.cc(50) : see declaration of 'method_name'
    1>        e:\test\main.cc(71) : see reference to function template instantiation 'base_caller *maker<T1,int,int,double>(R (__thiscall T1::* )(A1,A2))' being compiled
    1>        with
    1>        [
    1>            R=int,
    1>            A1=int,
    1>            A2=double
    1>        ]
    Lavock : ton code ne compile pas plus malheureusement car il ne peut pas déduire le parametre de template a partir du parametre de méthode.

  4. #4
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 104
    Par défaut
    Merci, avec ce message d'erreur on y voit plus clair
    Citation Envoyé par screetch Voir le message
    a local variable cannot be used as a non-type argument
    En effet, le paramètre method_name est une valeur, que j'essaie de passer en paramètre au template. On n'y voit pas très clair avec la déclaration de method_name, ça sera mieux avec des entiers. En gros, c'est comme si j'avais écrit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename C, typename R, typename A1, typename A2, int I>
    class exec
    {
    ...
    };
     
    template<typename C, typename R, typename A1, typename A2>
    base_caller* maker( int i )
    {
      return &exec<C, R, A1, A2, i>::instance;
    }
    Et là on voit bien que j'essaie de passer une variable locale en paramètre au template, ce qui ne risque pas de fonctionner.

  5. #5
    Membre chevronné Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Par défaut
    Citation Envoyé par j-jorge Voir le message

    Et là on voit bien que j'essaie de passer une variable locale en paramètre au template, ce qui ne risque pas de fonctionner.
    On peut passer une variable a une template, mais il faut que ce soit au choix:
    • un entier ou un type enuméré
    • un pointeur (objet ou fonction)
    • un lvalue ref(objet ou fonction)
    • un pointeur à un membre (<== ton cas si je ne m'abuse)

  6. #6
    screetch
    Invité(e)
    Par défaut
    non on ne peut pas passer une variable en parametre de template on ne peut passer qu'une constante de compilation, or ce n'est pas ce que faisait l'auteur.

  7. #7
    Membre expérimenté

    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 104
    Par défaut
    Citation Envoyé par Lavock Voir le message
    On peut passer une variable a une template, mais il faut que ce soit au choix:
    • un entier ou un type enuméré
    • un pointeur (objet ou fonction)
    • un lvalue ref(objet ou fonction)
    • un pointeur à un membre (<== ton cas si je ne m'abuse)
    Il faut aussi que ce soit une constante connue à la compilation. Or, en passant l'adresse de la méthode en paramètre à 'maker()', on perd ce statut de constante. Imaginons que j'appelle la fonction maker(), telle que je l'ai écrite dans mon premier post, avec deux méthodes ayant la même signature. Le compilateur va définir une seule implémentation de maker(), mais le type retourné devrait être différent pour chaque méthode. Ce qui est problématique.

    Il faudrait donc que l'adresse de la méthode apparaisse dans les paramètres templates de maker(), et soit déduit du paramètre passé à l'appel. Je ne vois pas encore comment. J'ai essayé quelque chose de proche de ta première réponse, mais j'ai la même erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template< typename C, typename R, typename A1, typename A2,
              R (C::*Method)(A1, A2) >
    base_caller* maker( R (C::*method_addr)(A1, A2) )
    {
      return &exec<C, R, A1, A2, Method>::instance;
    }

  8. #8
    Membre chevronné Avatar de Lavock
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 560
    Par défaut
    Erf, c'est pas évident là, mais je vois pas ce qui cloche. Peut-être essayé de passer par référence de fonction plutôt ? Remarque, je vois pas pourquoi ça marcherait mieux >< !

Discussions similaires

  1. Réponses: 6
    Dernier message: 04/06/2010, 11h37
  2. Fonction template, erreur interne du compilateur
    Par Emiler dans le forum Langage
    Réponses: 9
    Dernier message: 08/04/2009, 12h14
  3. [BOOST] erreur interne du compilateur
    Par venomelektro dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 15/04/2006, 18h08
  4. Message d'erreur Internal process...
    Par Systemic7 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 19/07/2005, 13h17
  5. Réponses: 3
    Dernier message: 13/08/2004, 09h35

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