¿Están ordenados los parámetros de C++ que no son de tipo para las plantillas (de funciones)?

StackOverflow https://stackoverflow.com/questions/112612

  •  02-07-2019
  •  | 
  •  

Pregunta

estoy hospedando Mono araña en un proyecto actual y le gustaría que las funciones de plantilla generen algunos de los métodos simples de obtención/establecimiento de propiedades, por ejemplo:

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

Usado:

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

Sin embargo, esto funciona bien si agrego 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;
}

¡Luego Visual C++ 9 intenta usar el contenedor JSObject* para 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, al emparejar JSObject* se produce un error de análisis.(inesperado '(').Probablemente se trate de un error de VC++ (¿alguien puede probar que "template void foo() {}" se compila en GCC?).Mismo error con "typedef JSObject* PObject;..., PObject TClassImpl::mem>", vacío, estructura indefinida* y doble.Dado que el uso de la función está completamente instanciado:"&ReadProp", no debería entrar en juego una semántica de sobrecarga de función normal, es una función definida en ese punto y tiene prioridad sobre las funciones de plantilla.Parece que el orden de la plantilla falla 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, tomado del encabezado:

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;
};
¿Fue útil?

Solución

Estoy bastante seguro de que VC++ tiene "problemas" aquí.Comeau y g++ 4.2 están contentos 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, no tiene nada de eso.

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

Otros consejos

Intente cambiar JSObject * a otro tipo de puntero para ver si eso reproduce el error.¿JSObject está definido en el punto de uso?Además, tal vez JSObject* deba estar entre paréntesis.

Ciertamente no soy un gurú de las plantillas, pero ¿se reduce esto a un caso sutil de intentar diferenciar las sobrecargas basándose únicamente en el tipo de retorno?

Dado que C++ no permite la sobrecarga de funciones según el tipo de retorno, quizás lo mismo se aplique a los parámetros de la plantilla.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top