title: Are C++ non-type parameters to (function) templates ordered?
body: <p>I am hosting <a href="http://developer.mozilla.org/En/SpiderMonkey/JSAPI_Reference" rel="nofollow noreferrer">SpiderMonkey</a> in a current project and would like to have template functions generate some of the simple property get/set methods, eg:</p>
  
  <pre><code>template &lt;typename TClassImpl, int32 TClassImpl::*mem&gt;
  JSBool JS_DLL_CALLBACK WriteProp(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
  {
      if (TClassImpl* pImpl = (TClassImpl*)::JS_GetInstancePrivate(cx, obj, &amp;TClassImpl::s_JsClass, NULL))
          return ::JS_ValueToInt32(cx, *vp, &amp;(pImpl-&gt;*mem));
      return JS_FALSE;
  }
  </code></pre>
  
  <p>Used:</p>
  
  <pre><code>::JSPropertySpec Vec2::s_JsProps[] = {
      {"x", 1, JSPROP_PERMANENT, &amp;JsWrap::ReadProp&lt;Vec2, &amp;Vec2::x&gt;, &amp;JsWrap::WriteProp&lt;Vec2, &amp;Vec2::x&gt;},
      {"y", 2, JSPROP_PERMANENT, &amp;JsWrap::ReadProp&lt;Vec2, &amp;Vec2::y&gt;, &amp;JsWrap::WriteProp&lt;Vec2, &amp;Vec2::y&gt;},
      {0}
  };
  </code></pre>
  
  <p>This works fine, however, if I add another member type:</p>
  
  <pre><code>template &lt;typename TClassImpl, JSObject* TClassImpl::*mem&gt;
  JSBool JS_DLL_CALLBACK WriteProp(JSContext* cx, JSObject* obj, jsval id, jsval* vp)
  {
      if (TClassImpl* pImpl = (TClassImpl*)::JS_GetInstancePrivate(cx, obj, &amp;TClassImpl::s_JsClass, NULL))
          return ::JS_ValueToObject(cx, *vp, &amp;(pImpl-&gt;*mem));
      return JS_FALSE;
  }
  </code></pre>
  
  <p>Then Visual C++ 9 attempts to use the JSObject* wrapper for int32 members!</p>
  
  <pre><code>1&gt;d:\projects\testing\jswnd\src\main.cpp(93) : error C2440: 'specialization' : cannot convert from 'int32 JsGlobal::Vec2::* ' to 'JSObject *JsGlobal::Vec2::* const '
  1&gt;        Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
  1&gt;d:\projects\testing\jswnd\src\main.cpp(93) : error C2973: 'JsWrap::ReadProp' : invalid template argument 'int32 JsGlobal::Vec2::* '
  1&gt;        d:\projects\testing\jswnd\src\wrap_js.h(64) : see declaration of 'JsWrap::ReadProp'
  1&gt;d:\projects\testing\jswnd\src\main.cpp(93) : error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'JSPropertyOp'
  1&gt;        None of the functions with this name in scope match the target type
  </code></pre>
  
  <p>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::<em>mem>", void</em>, struct Undefined*, and double. Since the function usage is fully instantiated: "&amp;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.</p>
  
  <p>Vec2 is just:</p>
  
  <pre><code>class Vec2
  {
  public:
      int32 x, y;
  
      Vec2(JSContext* cx, JSObject* obj, uintN argc, jsval* argv);
  
      static ::JSClass s_JsClass;
      static ::JSPropertySpec s_JsProps[];
  };
  </code></pre>
  
  <p>JSPropertySpec is described in JSAPI link in OP, taken from header:</p>
  
  <pre><code>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;
  };
  </code></pre>