键入参数到(功能)模板排序?

我在当前项目中托管SpiderMonkey,并希望模板函数生成一些简单的属性get / set方法,例如:

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

用过的:

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

这工作正常,但是,如果我添加另一个成员类型:

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

然后Visual C ++ 9尝试为int32成员使用JSObject *包装器!

1>d:projectstestingjswndsrcmain.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:projectstestingjswndsrcmain.cpp(93) : error C2973: 'JsWrap::ReadProp' : invalid template argument 'int32 JsGlobal::Vec2::* '
1>        d:projectstestingjswndsrcwrap_js.h(64) : see declaration of 'JsWrap::ReadProp'
1>d:projectstestingjswndsrcmain.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

令人惊讶的是,削弱JSObject *会产生一个解析错误! ('unexpected'(')。这可能是一个VC ++错误(任何人都可以测试“模板void foo(){}”在GCC中编译?)。“typedef JSObject * PObject; ...,PObject TClassImpl :: mem>“,void,struct Undefined *和double。由于函数的用法已经完全实例化:”&ReadProp“,所以不应该有正常的函数重载语义发挥作用,它是一个已定义的函数,并且优先于模板函数,看起来这里的模板排序失败了。

Vec2只是:

class Vec2
{
public:
    int32 x, y;

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

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

JSPropertySpec在OP中的JSAPI链接中描述,取自标题:

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

很确定VC ++在这里有“问题”。 Comeau和g ++ 4.2都对以下程序感到满意:

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没有它。

我没有时间仔细阅读我的标准以找出究竟是什么......但我认为VC ++在这里是错误的。


尝试将JSObject *更改为另一种指针类型,以查看是否会再现错误。 JSObject是在使用时定义的? 另外,也许JSObject *需要在parens中。


我当然不是模板大师,但是这是否可以归结为一种微妙的情况:试图区分纯粹基于返回类型的重载?

由于C ++不允许基于返回类型重载函数,可能同样的情况适用于模板参数。

链接地址: http://www.djcxy.com/p/66529.html

上一篇: type parameters to (function) templates ordered?

下一篇: How to save image with custom name in iPhone album?