Template compiling errors porting from Windows code

Discussion in 'iOS Programming' started by DidierMalenfant, May 21, 2010.

  1. DidierMalenfant macrumors newbie

    Joined:
    May 21, 2010
    #1
    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
     
  2. TiberiusXavier macrumors member

    Joined:
    Apr 18, 2010
    Location:
    Chicago
    #2
    Can you provide a more complete template definition?

    What is the T in CSimpleKey<T>?
     
  3. DidierMalenfant thread starter macrumors newbie

    Joined:
    May 21, 2010
    #3
    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;
     
  4. TiberiusXavier macrumors member

    Joined:
    Apr 18, 2010
    Location:
    Chicago
    #4
    How is BinarySearch declared? Is it a static template method or template class?
     
  5. DidierMalenfant thread starter macrumors newbie

    Joined:
    May 21, 2010
    #5
    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;
    
    };
    
     
  6. TiberiusXavier macrumors member

    Joined:
    Apr 18, 2010
    Location:
    Chicago
    #6
    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);
        }
    };
    
     
  7. DidierMalenfant thread starter macrumors newbie

    Joined:
    May 21, 2010
    #7
    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.
     
  8. TiberiusXavier macrumors member

    Joined:
    Apr 18, 2010
    Location:
    Chicago
    #8
    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)?
     
  9. DidierMalenfant thread starter macrumors newbie

    Joined:
    May 21, 2010
    #9
    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.
     
  10. DidierMalenfant thread starter macrumors newbie

    Joined:
    May 21, 2010
    #10
    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!
     

Share This Page