【问题标题】:Are C++ non-type parameters to (function) templates ordered?(函数)模板的 C++ 非类型参数是否有序?
【发布时间】:2010-09-11 20:58:49
【问题描述】:

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

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 尝试将 JSObject* 包装器用于 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

令人惊讶的是,解析 JSObject* 会导致解析错误! (意外的'(')。这可能是一个 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;
};

【问题讨论】:

    标签: c++ templates overloading


    【解决方案1】:

    很确定 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++ 在这里是错误的。

    【讨论】:

    • 这似乎很可能 :'( 有人在 Connect 中放了一个错误吗?
    • 在将其提交到 Connect 之前,我想通读一下规范。然而,从规范中找出 VC++ 是否错误将是非常重要的。也许发布到 comp.whatever-it-is.c++ 看看他们中的一个是否可以语言律师并发布章节和诗句?
    • 好吧,我的意思是看看这是否是一个已知问题(事实证明是)。我的英语很差。 connect.microsoft.com/VisualStudio/feedback/…
    • 是的。 “不符合分类标准”的已知错误。哼哼。
    • 啊,过去的美好时光。在我的代表历史中看到这一点促使我确保这是固定的,至少在 VS2012 中是这样。连接bug还是WontFix有点糊涂。
    【解决方案2】:

    我当然不是模板专家,但这是否可以归结为尝试仅根据返回类型区分重载的微妙案例?

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

    【讨论】:

    • 不,只允许模板参数不同的重载函数。
    • “int class:*member”类型是指向成员int的指针,而不是成员函数
    • 当然,不应该在周日尝试思考!我以为它缺少一些括号...
    【解决方案3】:

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

    【讨论】:

    • 这里不需要更多的括号。它不像是指向成员函数的指针;这只是一个指向成员的指针。
    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    相关资源
    最近更新 更多