views:

66

answers:

4

I'm trying to use friend functions to overload << and templates to get familiar with templates. I do not know what these compile errors are:

Point.cpp:11: error:  shadows template parm 'class T'
Point.cpp:12: error: declaration of 'const Point<T>& T'

for this file

#include "Point.h"

template <class T>
Point<T>::Point() : xCoordinate(0), yCoordinate(0)
{}

template <class T>
Point<T>::Point(T xCoordinate, T yCoordinate) : xCoordinate(xCoordinate), yCoordinate(yCoordinate)
{}

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &T)
{
    std::cout << "(" << T.xCoordinate << ", " << T.yCoordinate << ")";
    return out;
}

My header looks like:

#ifndef POINT_H
#define POINT_H

#include <iostream>

template <class T>
class Point
{
public:
    Point();
    Point(T xCoordinate, T yCoordinate);
    friend std::ostream &operator<<(std::ostream &out, const Point<T> &T);

private:
    T xCoordinate;
    T yCoordinate;
};

#endif

My header also gives the warning:

Point.h:12: warning: friend declaration 'std::ostream& operator<<(std::ostream&, const Point<T>&)' declares a non-template function

Which I was also unsure why. Any thoughts? Thanks.

+1  A: 

Both the template parameter and the function parameter have the same name. Change it to something like:

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &point)
{
    std::cout << "(" << point.xCoordinate << ", " << point.yCoordinate << ")";
    return out;
}

The declaration of the friend function in the header should be changed too:

template <class G>
friend std::ostream &operator<<(std::ostream &out, const Point<G> &point);
Firas Assaad
do the template <class T> and <class G> in your comments have to be different for header and implementation files? Or can they both be class T?
Crystal
The problem is with the nested <class T> in the header file which will give you a similar shadowing error. You can have the same type parameter names in both files if you make both of them G or U or whatever you like.
Firas Assaad
A: 

sorry..msg deleted..was a wrong understanding of problem.

GauravG
A: 

@Firas has already answered your first question, so I won't repeat that here.

For your second question, it's warning you about this:

friend std::ostream &operator<<(std::ostream &out, const Point<T> &T);

This declaration is in a class template:

template <class T>
class Point { // ...

It's telling you that even though you can instantiate Point over many different types, you're saying that a non -template operator<< is a friend to all of them. I.e., even though there is a potentially unbounded set of different kinds of Points, you've said there's only one operator<< for them.

In fact, this appears to be a mistake in your code -- you've defined operator<< as a function template, but declared a (non-template) function as the friend of the class (one that your code doesn't seem to define). IOW, this definition:

template <class T>
std::ostream &operator<<(std::ostream &out, const Point<T> &T)

...is of a template, which is not the same thing as you've pointed to in the friend declaration above (even though I think you intended them to match).

Jerry Coffin
A: 

You have a subtle error here (unrelated): the definition of template methods are best tucked in the header because they should (usually) be visible to the caller.

For your compile issue: as the warning says, you are attempting to declare a non template friend function. Should you correct it, then the problem would magically be solved.

template <class T>
class Point
{
public:
  template <class U>
  friend std::ostream& operator<<(std::ostream& out, const Point<T>& p);
};

But the real question is do you need a friend declaration here ? Surely the x and y coordinates are accessible to the public (at least in read-only mode) ?

// Free functions
template <class T>
std::ostream& operator<<(std::ostream& out, const Point<T>& p)
{
  return out << '(' << p.x() << ", " << p.y() << ')';
}

Finally, do note that it would be best if your argument had a different name from the types in the scope, and notably the types you declared using the template syntax.

Matthieu M.