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;
}