[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