[C con Clase] Un error con (¿...?) en GCC y no en Visual Studio (Parte III)

Gilberto Cuba Ricardo gilbert en ucp.ho.rimed.cu
Vie Jul 9 21:42:32 CEST 2010


Hola Lista,

  He mantenido este título porque sigo teniendo errores durante una
  portación de códigos de Microsoft Visual Studio 2005 a GNU C/C++
  Compiler 3.4x >. Esta vez no he dejado el tema de las plantillas en
  el asunto porque a mi entender no lo es, pero no dejan de existir en
  mi código.

  A continuación muestro la lógica seguida y la generación de los
  códigos de errores que me van sucediendo. Una abstracción del código
  inicial donde me da el problema es el siguiente:

  ----------------------------------------------------
  #include <string>

    class IClassTypeInfo
      {
        /* ... */
      };

    template <class T>
    class vmt_definition : public IClassTypeInfo
      {
        public:
          template <typename RT>
          void def_method(const std::string& name, RT (T::* fn) () )
            {
            }
        /* ... */
      };

    template < class Current, class Descendant >
    struct definition;

    template <class T>
    class ScriptType
      {
        public:
          template<class U>
          static IClassTypeInfo* resolve_definition()
            {
[1]              static definition<U, U> d_;
              return &d_;
            }
        /* ... */
      };

    template <class T>
    class BasicScriptable : public ScriptType<T>
      {
        typedef ScriptType<T> self_t;
        /* ... */
      };

    class HeritableClass : public BasicScriptable<HeritableClass>
      {
      public:
        HeritableClass() {}
      public:
        void hered_first_method() {}
        void hered_second_method() {}
      };

    class MyFirstClass : public HeritableClass
      {
      public:
        virtual void method01() {}
      };

    class MyHeritClass : public MyFirstClass
      {
      public:
[2]        virtual IClassTypeInfo* get_typeInfo() { return resolve_definition<MyHeritClass>(); }
      public:
        virtual void method_01() {}
        virtual void method_02() {}
      };


  template<typename T>
  struct definition<MyFirstClass, T> : public vmt_definition<T>
    {
      definition()
        {
[3]          def_method( "method1", &MyFirstClass::method01 );
        }
    };

  template<typename T>
  struct definition<MyHeritClass, T> : public definition<MyFirstClass, T>
    {
      definition()
[4]        {
[5]          def_method( "method_01", &MyHeritClass::method_01 );
        }
    };

  int main()
  {
    return 0;
  }
  ----------------------------------------------------

  Como he comentado anteriormente, este código compila bien con
  Microsoft Visual Studio 2005 (MSVC), no siendo así con GCC 3.4.5 y
  todas las demás versiones hasta la 4.5 en las que he probado. Los
  errores que devuelve gcc son los siguientes:

|In constructor `definition<MyFirstClass, T>::definition()':|
- [3]**|error: there are no arguments to `def_method' that depend on a template parameter, so a declaration of `def_method' must be available|
- [3]**|error: (if you use `-fpermissive', G++ will accept your code, but allowing the use of an undeclared name is deprecated)|

|In constructor `definition<MyHeritClass, T>::definition()':|
- [5]**|error: there are no arguments to `def_method' that depend on a template parameter, so a declaration of `def_method' must be available|

|In constructor `definition<MyFirstClass, T>::definition() [with T = MyHeritClass]':|
- [4]|instantiated from `definition<MyHeritClass, T>::definition() [with T = MyHeritClass]'|
- [1]|instantiated from `static IClassTypeInfo* ScriptType<T>::resolve_definition() [with U = MyHeritClass, T = HeritableClass]'|
- [2]|instantiated from here|
- [3]**|error: no matching function for call to `definition<MyFirstClass, MyHeritClass>::def_method(const char[8], void (MyFirstClass::*)())'|

  Evidentemente para mí, y porque ya me lo explicaron en anteriores
  mensajes de este tipo, los tres primeros errores los entiendo y
  entonces modifico estás dos líneas [3] y [5] por:

[3]          vmt_definition<MyFirstClass>::def_method( "method1", &MyFirstClass::method01 );

[5]          vmt_definition<MyHeritClass>::def_method( "method_01", &MyHeritClass::method_01 );

  y he solucionado estos tres primeros errores en GCC pero he metido
  el ruido del último error ya no sólo en GCC, sino también en MSVC
  con el mensaje de:

- [3]: error C2352: 'vmt_definition<T>::def_method' : illegal call of non-static member function
        with
        [
            T=MyFirstClass
        ]
        --(17) : see declaration of 'vmt_definition<T>::def_method'
        with
        [
            T=MyFirstClass
        ]
        - ([3] - 2 líneas) : while compiling class template member function 'definition<Current,Descendant>::definition(void)'
        with
        [
            Current=MyFirstClass,
            Descendant=MyHeritClass
        ]
        - ([4] - 2 líneas) : see reference to class template instantiation 'definition<Current,Descendant>' being compiled
        with
        [
            Current=MyFirstClass,
            Descendant=MyHeritClass
        ]
        - [1] : see reference to class template instantiation 'definition<Current,Descendant>' being compiled
        with
        [
            Current=MyHeritClass,
            Descendant=MyHeritClass
        ]
        - [2] : see reference to function template instantiation 'IClassTypeInfo *ScriptType<T>::resolve_definition<MyHeritClass>(void)' being compiled
        with
        [
            T=HeritableClass
        ]

  La verdad es que el mensaje de error en MSVC pudiera ayudar un
  poquito más pero es que "def_method" es un método de
  "vmt_definition" y de esta clase es que hereda la especialización
  de la estructura "definition", por lo que es permisible hacer una
  llamada desde el constructor de la estructura a un método de una
  clase que se hereda.

  A pesar de todo esto tengo mis sospechas sobre dónde es, pero no
  sabría como solucionarlo. Veamos, si comento [1] y por supuesto la
  línea que le sigue del "return &d_;" todo compila de maravillas en
  los dos compiladores. ¡Es verdad que es para mearse! :-) Yo llevo
  varios días con insonnio pensado en esto, pero ya he estado a punto
  de cambiarlo todo por completo.

  Alguien pudiera decirme o darme una pista de qué es lo que está
  sucediendo, porque realmente no entiendo mucho la situación.

  Disculpen por el mensaje tan grande y ojala la paciencia les de para
  entenderlo. :)

-- 
Salu2,
 Gilbert





Más información sobre la lista de distribución Cconclase