2008-09-22 25 views
5

Estoy recibiendo SpiderMonkey en un proyecto actual y me gustaría tener funciones de plantilla generan algunos de los métodos get/set sencilla de propiedad, por ejemplo:¿Están pedidos los parámetros C++ no de tipo para (función)?

template <typename TClassImpl, int32 TClassImpl::*mem> 
JSBool JS_DLL_CALLBACK WriteProp(JSContext* cx, JSObject* obj, jsval id, jsval* vp) 
{ 
    if (TClassImpl* pImpl = (TClassImpl*)::JS_GetInstancePrivate(cx, obj, &TClassImpl::s_JsClass, NULL)) 
     return ::JS_ValueToInt32(cx, *vp, &(pImpl->*mem)); 
    return JS_FALSE; 
} 

usados:

::JSPropertySpec Vec2::s_JsProps[] = { 
    {"x", 1, JSPROP_PERMANENT, &JsWrap::ReadProp<Vec2, &Vec2::x>, &JsWrap::WriteProp<Vec2, &Vec2::x>}, 
    {"y", 2, JSPROP_PERMANENT, &JsWrap::ReadProp<Vec2, &Vec2::y>, &JsWrap::WriteProp<Vec2, &Vec2::y>}, 
    {0} 
}; 

Esto funciona bien, Sin embargo, si añado otro tipo de miembro:

template <typename TClassImpl, JSObject* TClassImpl::*mem> 
JSBool JS_DLL_CALLBACK WriteProp(JSContext* cx, JSObject* obj, jsval id, jsval* vp) 
{ 
    if (TClassImpl* pImpl = (TClassImpl*)::JS_GetInstancePrivate(cx, obj, &TClassImpl::s_JsClass, NULL)) 
     return ::JS_ValueToObject(cx, *vp, &(pImpl->*mem)); 
    return JS_FALSE; 
} 

a continuación, Visual C++ 9 intentos de utilizar la JSObject * envoltorio para los miembros Int32!

1>d:\projects\testing\jswnd\src\main.cpp(93) : error C2440: 'specialization' : cannot convert from 'int32 JsGlobal::Vec2::* ' to 'JSObject *JsGlobal::Vec2::* const ' 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 
1>d:\projects\testing\jswnd\src\main.cpp(93) : error C2973: 'JsWrap::ReadProp' : invalid template argument 'int32 JsGlobal::Vec2::* ' 
1>  d:\projects\testing\jswnd\src\wrap_js.h(64) : see declaration of 'JsWrap::ReadProp' 
1>d:\projects\testing\jswnd\src\main.cpp(93) : error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'JSPropertyOp' 
1>  None of the functions with this name in scope match the target type 

Sorprendentemente, parening JSObject * incurre en un error de análisis! (inesperado '('). Este es probablemente un error de VC++ (¿alguien puede probar que "template void foo() {}" compila en GCC?). Mismo error con "typedef JSObject * PObject; ..., PObject TClassImpl :: mem> ", void, struct Undefined * y double. Como el uso de la función está completamente instanciado:" & ReadProp ", no debería haber una semántica de sobrecarga de función normal que entra en juego, es una función definida en ese punto y obtiene . prioridad sobre las funciones de plantilla parece el ordenamiento plantilla está fallando aquí

Vec2 es simplemente:.

class Vec2 
{ 
public: 
    int32 x, y; 

    Vec2(JSContext* cx, JSObject* obj, uintN argc, jsval* argv); 

    static ::JSClass s_JsClass; 
    static ::JSPropertySpec s_JsProps[]; 
}; 

JSPropertySpec se describe en el enlace JSAPI en OP, tomada desde la cabeza er:

typedef JSBool 
(* JS_DLL_CALLBACK JSPropertyOp)(JSContext *cx, JSObject *obj, jsval id, 
           jsval *vp); 

... 

struct JSPropertySpec { 
    const char  *name; 
    int8   tinyid; 
    uint8   flags; 
    JSPropertyOp getter; 
    JSPropertyOp setter; 
}; 

Respuesta

3

Bastante seguro que VC++ tiene "problemas" aquí. Comeau y g ++ 4.2 son ambos feliz con el siguiente programa:

struct X 
{ 
    int i; 
    void* p; 
}; 

template<int X::*P> 
void foo(X* t) 
{ 
    t->*P = 0; 
} 

template<void* X::*P> 
void foo(X* t) 
{ 
    t->*P = 0; 
} 

int main() 
{ 
    X x; 
    foo<&X::i>(&x); 
    foo<&X::p>(&x); 
} 

VC++ 2008SP1, sin embargo, está teniendo ninguno de él.

No tengo tiempo de leer mi estándar para saber exactamente qué es qué ... pero creo que VC++ está equivocado aquí.

+0

Esto parece probable: '( ¿Alguien ha puesto un error en Connect todavía? –

+0

Me gustaría leer las especificaciones antes de archivar esto en Connect. Sin embargo, averiguar si VC++ está equivocado de la especificación no será trivial. Posiblemente publique en comp.whatever-it-is.C++ para ver si uno de ellos puede subir de categoría y publicar un capítulo y un versículo? – DrPizza

+0

Bueno, quería ver si esto es un problema conocido (resulta que sí lo es). Mi inglés es el malo. https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362170 –

0

Intente cambiar el JSObject * a otro tipo de puntero para ver si eso reproduce el error. ¿Está JSObject definido en el punto de uso? Además, tal vez JSObject * debe estar en parens.

+0

No se necesitan más paréntesis aquí. No es como un puntero a la función miembro; esto es solo un puntero al miembro. – DrPizza

0

Definitivamente no soy un gurú de plantilla, pero ¿se reduce esto a un caso sutil de tratar de diferenciar sobrecargas basadas únicamente en el tipo de devolución?

Dado que C++ no permite la sobrecarga de funciones basadas en el tipo de retorno, quizás lo mismo se aplica a los parámetros de la plantilla.

+0

No, las funciones sobrecargadas que difieren solo por los argumentos de la plantilla están permitidas. – DrPizza

+0

El tipo "clase int: * miembro" es un puntero a un miembro int, no a una función miembro –

+0

Por supuesto, ¡no intente pensar en los domingos! Pensé que faltaba un paréntesis ... –

Cuestiones relacionadas