type parameters to (function) templates ordered?
I am hosting SpiderMonkey in a current project and would like to have template functions generate some of the simple property get/set methods, eg:
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;
}
Used:
::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}
};
This works fine, however, if I add another member type:
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;
}
Then Visual C++ 9 attempts to use the JSObject* wrapper for int32 members!
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
Surprisingly, parening JSObject* incurs a parse error! (unexpected '('). This is probably a VC++ error (can anyone test that "template void foo() {}" compiles in GCC?). Same error with "typedef JSObject* PObject; ..., PObject TClassImpl::mem>", void, struct Undefined*, and double. Since the function usage is fully instantiated: "&ReadProp", there should be no normal function overload semantics coming into play, it is a defined function at that point and gets priority over template functions. It seems the template ordering is failing here.
Vec2 is just:
class Vec2
{
public:
int32 x, y;
Vec2(JSContext* cx, JSObject* obj, uintN argc, jsval* argv);
static ::JSClass s_JsClass;
static ::JSPropertySpec s_JsProps[];
};
JSPropertySpec is described in JSAPI link in OP, taken from header:
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;
};
Pretty sure VC++ has "issues" here. Comeau and g++ 4.2 are both happy with the following program:
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, however, is having none of it.
I haven't the time to read through my standard to find out exactly what's what... but I think VC++ is in the wrong here.
Try changing the JSObject * to another pointer type to see if that reproduces the error. Is JSObject defined at the point of use? Also, maybe JSObject* needs to be in parens.
I am certainly no template guru, but does this boil down to a subtle case of trying to differentiate overloads based purely on the return type?
Since C++ doesn't allow overloading of functions based on return type, perhaps the same thing applies to template parameters.
链接地址: http://www.djcxy.com/p/66530.html下一篇: 键入参数到(功能)模板排序?