Друзья, шаблоны, перегрузка << - PullRequest
4 голосов
/ 03 июня 2010

Я пытаюсь использовать функции друзей для перегрузки << и шаблоны для ознакомления с шаблонами. Я не знаю, что это за ошибки компиляции: </p>

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

для этого файла

#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;
}

Мой заголовок выглядит так:

#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

Мой заголовок также выдает предупреждение:

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

Что я тоже был не уверен, почему. Какие-нибудь мысли? Спасибо.

Ответы [ 3 ]

3 голосов
/ 03 июня 2010

И параметр шаблона, и параметр функции имеют одно и то же имя. Измените его на что-то вроде:

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

Также необходимо изменить объявление функции друга в заголовке:

template <class G>
friend std::ostream &operator<<(std::ostream &out, const Point<G> &point);
1 голос
/ 03 июня 2010

@ Firas уже ответил на ваш первый вопрос, поэтому я не буду повторять это здесь.

Ваш второй вопрос предупреждает вас об этом:

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

Это объявление в шаблоне класса:

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

Он говорит вам, что даже если вы можете создать экземпляр Point для множества различных типов, вы говорите, что non -темплет operator<< является другом для всех из них. То есть, хотя существует потенциально неограниченный набор различных типов Point с, вы сказали, что для них есть только один operator<<.

На самом деле, это кажется ошибкой в ​​вашем коде - вы определили operator<< как шаблон функции, но объявили функцию (не шаблонную) как друг класса (тот, которого ваш код, похоже, не определяет). IOW, это определение:

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

... относится к шаблону, который не - это то же самое, на которое вы указали в объявлении друга выше (хотя я думаю, что вы намеревались сопоставить их).

0 голосов
/ 03 июня 2010

Здесь есть небольшая ошибка (не связанная): определение шаблонных методов лучше всего скрыть в заголовке, потому что они должны (обычно) быть видимыми для вызывающей стороны.

Для вашей проблемы компиляции: как предупреждениеговорит, что вы пытаетесь объявить не шаблонную функцию друга.Если вы исправите это, тогда проблема будет волшебным образом решена.

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

Но реальный вопрос в том, нужна ли вам здесь декларация friend?Конечно, координаты x и y доступны для общественности (по крайней мере, в режиме только для чтения)?

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

Наконец, обратите внимание, что было бы лучше, если бы ваш аргумент имел другое имяиз типов в области, и в частности типов, которые вы объявили с использованием синтаксиса template.

...