是否对(函数)模板的C ++非类型参数进行了排序?
时间:2020-03-06 14:31:07 来源:igfitidea点击:
我正在当前项目中托管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:\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; };
解决方案
尝试将JSObject *更改为另一种指针类型,以查看是否会重现该错误。是否在使用时定义了JSObject?另外,也许JSObject *需要放在括号内。
我当然不是模板专家,但这是否可以归结为试图仅基于返回类型来区分重载的微妙情况?
由于C ++不允许基于返回类型的函数重载,因此也许同样的情况适用于模板参数。
可以肯定的是,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 ++在这里是错误的。