0

When compiling this code (part of SpiderMonkey):

template<IsAcceptableThis Test, NativeImpl Impl>
JS_ALWAYS_INLINE bool
CallNonGenericMethod(JSContext *cx, CallArgs args)
{
    const Value &thisv = args.thisv();
    if (Test(thisv))
        return Impl(cx, args);

    return detail::CallMethodIfWrapped(cx, Test, Impl, args);
}

template<Value ValueGetter(JSObject *obj)>
static JSBool
Getter(JSContext *cx, unsigned argc, Value *vp)
{
    CallArgs args = CallArgsFromVp(argc, vp);
    return CallNonGenericMethod<ThisTypeArray::IsThisClass,
                                ThisTypeArray::GetterImpl<ValueGetter> >(cx, args);
}

I get this error, related to the invocation of CallNonGenericMethod.

error : template parameter 'ValueGetter' of type 'JS::Value ()(JSObject*)' is not allowed in an integral constant expression because it is not of integral or enumeration type*

where ValueGetter is

inline Value
TypedArray::lengthValue(JSObject *obj)
{
    JS_ASSERT(obj->isTypedArray());
    return obj->getFixedSlot(LENGTH_SLOT);
}

and

template<Value ValueGetter(JSObject *obj)>
static bool
GetterImpl(JSContext *cx, CallArgs args)
{
    JS_ASSERT(IsThisClass(args.thisv()));
    args.rval().set(ValueGetter(&args.thisv().toObject()));
    return true;
}

I couldn't find any helpful information online, and I'm struggling to find what the problem is. Can anyone please clarify?

Many thanks.

rippeltippel
  • 369
  • 1
  • 7
  • 15
  • `template`: What is this meant to be? – John Dibling Jan 14 '14 at 12:54
  • Probably the okd compiler (4.1.1). Try passing a function pointer instead of a function? – Yakk - Adam Nevraumont Jan 14 '14 at 13:04
  • 2006 isn't _that_ old – Lightness Races in Orbit Jan 14 '14 at 13:23
  • It would be better to post a [testcase](http://sscce.org). What is `ThisTypeArray::GetterImpl`? We can't really see that the template parameter's existence is a problem: the problem could be in its usage. – Lightness Races in Orbit Jan 14 '14 at 13:26
  • @LightnessRacesinOrbit That's the real issue. Without seeing the definition of `ThisTypeArray::GetterImpl`, it's impossible to even guess about what's going on. (The error message suggests that it requires an integer as its template argument. But I've learned to mistrust error messages where templates are concerned. – James Kanze Jan 14 '14 at 13:34
  • @JamesKanze: Precisely. I wholly admit my answer is just a guess, but I'll leave it anyway in case it turns out to be correct and the OP can _accept_ it whilst I'm gone for the afternoon ;) – Lightness Races in Orbit Jan 14 '14 at 13:36
  • @LightnessRacesinOrbit If I were guessing, I'd guess that there's a problem due to trying to use a pointer to a member function in a context where a pointer to function is required. But that's just because that seems to be a fairly frequent error. – James Kanze Jan 14 '14 at 13:37
  • Thank you for your advice, just added the definition of GetterImpl. It basically makes a check and then invokes the template parameter (ValueGetter) with the given arguments. – rippeltippel Jan 14 '14 at 13:39
  • @rippeltippel: And now we'd need to know what `args.rval().set` is. This is why you construct a [testcase](http://sscce.org). – Lightness Races in Orbit Jan 14 '14 at 15:03

2 Answers2

2

This is supposed to work, you are passing a function, and C++ is supposed to turn it into a function pointer. Maybe you make that function pointer explicit:

template<Value (*ValueGetter)(JSObject *obj)>
pentadecagon
  • 4,717
  • 2
  • 18
  • 26
1

[C++11: 14.1/4]: A non-type template-parameter shall have one of the following (optionally cv-qualified) types:

  • integral or enumeration type,
  • pointer to object or pointer to function,
  • lvalue reference to object or lvalue reference to function,
  • pointer to member,
  • std::nullptr_t.

But a pointer to function doesn't look like this:

Value ValueGetter(JSObject *obj)

It looks like this:

Value (*ValueGetter)(JSObject *obj)

Then again:

[C++11: 14.1/8]: A non-type template-parameter of type “array of T” or “function returning T is adjusted to be of type “pointer to T” or “pointer to function returning T, respectively.

The same wording exists in C++03, at the same location.

So, your code is valid and you have a compiler bug on your hands.

Perhaps you can work around it by adjusting the template-parameter yourself, though it'll depend what the bug is.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055