views:

88

answers:

3

I'm porting over some templated code from Windows and I'm hitting some compiler differences on the iPhone 3.2 SDK.

Original code inside a class template's member function is:

return BinarySearch<uint32, CSimpleKey<T> >(key);

where BinarySearch is a method inherited from another template.

This produces the following error:

csimplekeytable.h:131: error: no matching function for call to 'BinarySearch(NEngine::uint32&)'

The visual studio compiler seems to walk up the template hierarchy fine but gcc needs me to fully qualify where the function comes from (I have verified this by fixing the same issues with template member variables that way).

So I now need to change this into:

return CSimpleTable<CSimpleKey<T> >::BinarySearch<uint32, CSimpleKey<T> >(key);

Which now produces the following error:

csimplekeytable.h:132: error: expected primary-expression before ',' token
csimplekeytable.h:132: error: expected primary-expression before '>' token

After some head scratching, I believe what's going on here is that it's trying to resolve the '<' before BinarySearch as a 'Less Than' operator for some reason.

So two questions: - Am I on the right path with my interpretation of the error? - How do I fix it?

-D

A: 

Maybe it's just a problem with the uint32 typedef. It could be that it's not available in the new environment. In the first case the namespace resolution picks up NEngine::uint32, in the second case it doesn't pick anything at all (hence the parsing error).

I suggest looking for how uint32 is defined on Windows, and try copying that definition over.

UncleZeiv
A: 

Perhaps it's because you've made your spacings inconsistent. You've done CSimpleTable<CSimpleKey<T> >, rather than CSimpleTable<CSimpleKey<T>>. I believe that they should both be valid, but perhaps there's a parser bug involved.

Edit: You could also try heading down the automatic argument type deduction route, and chopping the explicit specialization.

DeadMG
The second is not valid because it's interpreted as a shift token. That's why the space is there, which forces it to be interpreted as two consequitive `>` tokens.
Johannes Schaub - litb
A: 

If CSimpleTable is the base class, you need to qualify your call with that base class name or alternatively with this. But since both of these depend on the template parameters, the compiler cannot lookup what the name BinarySearch means. It could be a static integer constant, which you compare against something else, or it could be a template that you put arguments enclosed in <...> for. You need to tell the compiler about the latter

/* the "::template" means: 'the name that follows is a template' */
return CSimpleTable<CSimpleKey<T> >::template BinarySearch<uint32, CSimpleKey<T> >(key);

Or with this

return this->template BinarySearch<uint32, CSimpleKey<T> >(key);

The reason for the qualification is that the compiler does not look for unqualified names in base classes that depend on template parameters (in your case the parameter is T), since the binding of the name would depend on whether the base class has such a name or not, which is considered unfortunate. For a plain name like BinarySearch, there is in addition no indication that this name depends on a template parameter, thus the Standard requires compilers not to delay lookup of the name until instantiation. So the name, even if lookup in dependent bases would be allowed on instantiation (which isn't), couldn't be found anyway.

You have to explicitly tell the compiler to look in the enclosing class by qualifying it, in which event the compiler will include dependent base classes during lookup when instantiating. Prefixing with this or the class name will also make the name dependent, thus delaying lookup of it until instantiation. These two facts are required for it to work.

Johannes Schaub - litb
Yes! "this->" works and for the reason you explain is a way more obvious choice. doh!Thanks!
Didier Malenfant