Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

DidierMalenfant

macrumors newbie
Original poster
May 21, 2010
7
0
I'm porting over some templated code and I'm hitting some compiler differences on the iPhone 3.2 SDK.

Original code inside a class template's member function is:
Code:
return BinarySearch<uint32, CSimpleKey<T> >(key);
where BinarySearch is a method inherited from another template.

This produces the following error:
Code:
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:
Code:
return CSimpleTable<CSimpleKey<T> >::BinarySearch<uint32, CSimpleKey<T> >(key);
Which now produces the following error:
Code:
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
 
Here's the template (some code removed):
Code:
template<class T> class CSimpleKey {
public:

    ...

    };

template<class T> class CSimpleKeyTable : public CSimpleTable<CSimpleKey<T> > {

    ...

public:
    uint32 FindKey(uint32 identifier);

    ...

    };
Here's the function where the error occurs:

Code:
template<class T> uint32 CSimpleKeyTable<T>::FindKey(uint32 key) {
    if(CSimpleTable<CSimpleKey<T> >::Used() == 0)
        return eNeverIndex;

    Prepare();                  // this will sort the table if necessary
    
    return CSimpleTable<CSimpleKey<T> >::BinarySearch<uint32, CSimpleKey<T> >(key);
    }
and in this case the key is a uint32 (taken from the offending instance)
Code:
CSimpleKeyTable<uint32> shadernames;
 
Code:
template<typename T> struct CSimpleTable {

    ...

    template<typename TKey, typename TC> uint32 BinarySearch(const TKey& key) const;
    template<typename TKey, typename TC> uint32 BinarySearch(const TKey* key) const;

};
 
Wait, is your template method not defined inside you template class definition?

It should be:
Code:
template<class T> class CSimpleKeyTable : public CSimpleTable<CSimpleKey<T> > {
    uint32 FindKey(uint32 key) {
        if( Used() == 0)
            return eNeverIndex;

        Prepare();                  // this will sort the table if necessary
     
        return BinarySearch<uint32, CSimpleKey<T> >(key);
    }
};
 
They are defined further down in the same header file, just for readability.

I tried including the definition with the declaration, as suggested, and get the same error.
 
You may be hitting a gray area where different compilers are free to implement a language feature. Can you encapsulate the base class instead or do you need the polymorphism?

Code:
template< typename T, typename K, typename CK > struct foo
{
    T m_value;
    
    uint32 BinarySearch( K & k ) const
    {
        CK filler = 0;
        return m_value + k + filler;
    }
};

template< typename T > struct bar
{
    typedef foo< T, uint32, uint32 > base_;

    base_ m_base;
    
    uint32 FindKey( uint32 key )
    {
        return m_base.BinarySearch( key );
    }
};

If not, would you be able to avoid using the baseclass template methods (perhaps sadly reimplementing them in the derived class)?
 
I can give it a try, if anything to produce more insight into the issue.

I think the main thing I seem to be hitting is the fact that cl.exe on Windows doesn't seem to evaluate any template code unless the stuff is actually used somewhere, whereas gcc seems to make sure everything is legit.

So the 'this stuff compiles on windows' might not even be true in my case.
 
Fixed it.

You suggestion made me try to encapsulate another table and access its BinarySearch function (which worked), which prompted me to try the (now obvious) solution:
Code:
template<class T> uint32 CSimpleKeyTable<T>::FindKey(uint32 key) {
    if(CSimpleTable<CSimpleKey<T> >::Used() == 0)
        return eNeverIndex;

    Prepare();                  // this will sort the table if necessary
    
    return this->BinarySearch<uint32, CSimpleKey<T> >(key);
    }

which is actually better than adding the template typename in front since this lets the compiler find the closest implementation of BinarySearch().

Thanks for the help!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.