Tutorial :Are C++ non-type parameters to (function) templates ordered?



Question:

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:\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  

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


Solution:1

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.


Solution:2

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.


Solution:3

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.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »