tags:

views:

1741

answers:

2

Hi,

I am wondering why the following contrived example code works perfectly fine in Visual Studio 2005, but generates an error in GCC ("no matching function to call" when calling Interpolate() as shown below).

Also, how do I work around this? It seems that the error message is just a generic message because GCC did not have a more specific message for the actual reason of the problem and it had to output something. I'm a bit at a loss on how to proceed porting this class without some really ugly workarounds.

namespace Geo
{
    template <class T>
    class TMyPointTemplate
    {
        T X,Y;
    public:
        inline TMyPointTemplate(): X(0), Y(0) {}
        inline TMyPointTemplate(T _X,T _Y): X(_X), Y(_Y) {}
        inline T GetX ()const { return X; }
        inline T GetY ()const { return Y; }
        //...
        template<T> TMyPointTemplate<T> Interpolate(const TMyPointTemplate<T> &OtherPoint)const
        {
            return TMyPointTemplate((X+OtherPoint.GetX())/2,(Y+OtherPoint.GetY())/2);
        }     
    };
    typedef TMyPointTemplate<int> IntegerPoint;
}

Geo::IntegerPoint Point1(0,0);
Geo::IntegerPoint Point2(10,10);
Geo::IntegerPoint Point3=Point1.Interpolate(Point2); //GCC PRODUCES ERROR: no matching function for call to 'Geo::TMyPointTemplate<int>::Interpolate(Geo::IntegerPoint&)'

Thanks for your help,

Adrian

+9  A: 

I don't think you need the template there at all in the function definition, since it is defined inline with the class

TMyPointTemplate Interpolate(const TMyPointTemplate &OtherPoint)const {

should do.

And when you do use the template for defining the function not inline, I think you need the class keyword in there like this.

template<class T> // <- here
TMyPointTemplate<T> TMyPointTemplate<T>::Interpolate(const TMyPointTemplate<T> &OtherPoint)const {
Evan Teran
Excellent answer. Thanks a lot for your help! :-)
Adrian Grigore
+7  A: 

Evan's answer addresses the issue, but I thought it might be useful to explain why.

As written, Interpolate is a member template function with a single unnamed 'non type template parameter' (rather than a type template parameter which is almost certainly what you intended). To show this, we can give that parameter a name:

template<T t> TMyPointTemplate<T> Interpolate
      (const TMyPointTemplate<T> &OtherPoint)const

And we can now see how to call that function, we just need to provide a value for 't':

Geo::IntegerPoint Point3=Point1.Interpolate <0> (Point2);

Adding class or typename before 'T' here, will declare it as a type template parameter. However, making just that change will result in an error since the identifier 'T' is already being used for the template parameter name in the enclosing class template. We must change the name of the template parameter for the member function template:

template <class T>
class TMyPointTemplate
{
public:
  //...
  template<class S> TMyPointTemplate<T> Interpolate
                 (const TMyPointTemplate<S> &OtherPoint) const
  {
    return ...;
  }                       
};
Richard Corden
Very insightful indeed. Thanks a lot for your help! :-)
Adrian Grigore