Оператор дружественного потока в C ++ 17 простого шаблона класса

У меня другой вопрос, потому что он относится к более новой версии C ++.

Этот вопрос уже задавался здесь, и я имею в виду этот ответ. Однако об этом спросили и ответили еще в 2009 году, и это довольно устарело для текущих компиляторов и версий языка C ++. Тем не мение; вот оно снова.

У меня есть простой шаблонный класс, который я хотел бы перегрузить оператором потока, но в моем случае здесь: я использую Visual Studio 2017 CE v4.6.01055 с функцией компилятора C ++, установленной на ISO C++ Latest Draft Standard (/std:c++latest), просто поместите C ++ 17. Я собираю его в режиме отладки x86.

Я пробовал решение из приведенного выше Q / A, но оно продолжает давать мне ошибки компилятора.

Вот простой класс

template<class T>
class Point {
public:
    T mX;
    T mY;

    Point() : mX(0), mY(0) {}
    Point( T x, T y ) : mX( x ), mY( y ) {}
    Point( T& x, T& y ) : mX( x ), mY( y ) {}
    Point( T* x, T* y ) : mX( *x ), mY( *y ) {}

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

В предложении говорилось, что вы должны сделать единственный экземпляр этого шаблона с именем specialization другом. Пользователь также заявил, что вам нужно поместить объявление operator<< над объявлением шаблона класса. Я пробовал это; Я попытался переместить метод из заголовка в cpp, ниже, выше; Я попытался даже поместить определение в класс, и не важно, что я пытаюсь; Не могу заставить его правильно скомпилировать.

Я даже нашел этот ответ и я попробовал шаблон там, но он все еще не работает в C ++ 17. По крайней мере, на данный момент это compiling без специализации <> и не может быть собран, но когда я добавляю это, он не может быть скомпилирован.

Каков правильный синтаксис и / или размещение для перегрузки оператора потока в качестве друга простого шаблона класса в c ++ 17? Я не обязательно имею в виду синтаксис самого operator<<() ... он должен был больше иметь дело с фактическим размещением объявлений и определений. Единственная часть синтаксиса, в которой я не был уверен, но выяснил из предыдущих ответов, которые я показал здесь, была часть о том, чтобы сделать его специализацией; эта часть была для меня новой.

ИЗМЕНИТЬ

Я не знаю, что вызвало ошибки компилятора или компоновщика. Заявления и определения были такими же. Я закончил тем, что изменил второй параметр с const Point<T>& на Point<T> в объявлениях и определении, и он скомпилирован и построен. Затем я снова изменил их на const Point<T>&, и теперь он компилируется, строится и выдает мне результат без ошибок.

Это могло быть ошибкой в ​​Visual Studio, поскольку вчера вечером я обновил ее до последней версии. Я не знаю, что было причиной этого; но то, что когда-либо было, теперь решено.


person Francis Cugler    schedule 10.03.2018    source источник
comment
Однако этот вопрос был задан и дан ответ еще в 2009 году, и он довольно устарел для текущих компиляторов и версий языка C ++. Как вы думаете, почему он устарел? Тот факт, что вопрос старый, не означает, что ответы еще не применимы. Все они по-прежнему являются легальным C ++.   -  person Nicol Bolas    schedule 10.03.2018
comment
@NicolBolas и компиляторы с годами меняются; синтаксис действительно меняется, вещи устаревают, добавляются новые функции. Вышла новая ОС.   -  person Francis Cugler    schedule 10.03.2018
comment
Должно быть friend std::ostream& operator<<(std::ostream& out, const Point<T>& p)   -  person Justin    schedule 10.03.2018
comment
Обычно я не уверен, делаю ли я базовые классы, не являющиеся шаблоном, я передаю значения по константной ссылке на оператор друга; Я предпочитаю использовать const ref.   -  person Francis Cugler    schedule 10.03.2018
comment
Он компилируется на C ++ 14, верно?   -  person gsquaredxc    schedule 10.03.2018
comment
Не пробовал, но использую c ++ 17   -  person Francis Cugler    schedule 10.03.2018
comment
Возможно, это была ошибка визуальной студии ... Я изменил второй параметр на Point<T>, а не на const Point<T>&, и он компилировался и собирался без ошибок. Затем я снова изменил его на const Point<T>&, и я думаю, что теперь он работает. Я только что обновился до последней версии Visual Studio вчера вечером.   -  person Francis Cugler    schedule 10.03.2018


Ответы (1)


Синтаксис дружественной функции почти такой же, как и для любой другой функции. В вашем случае вы бы сделали:

friend std::ostream& operator<< (std::ostream& out, const Point<T>& p )
{
    //do whatever
    return out;
}

Это создает оператор, который принимает Point<T> и печатает его так, как вы хотите. Дополнительную информацию см. здесь.
РЕДАКТИРОВАТЬ:
С точки зрения использования и размещения вы можете использовать функцию только тогда, когда класс определен, поэтому обычно объявляется в тех же файлах, что и ваш класс. Единственное реальное различие между функцией класса friend и функцией шаблона friend состоит в том, что компилятор должен интерпретировать функцию friend для каждого типа данных, которым является объект friend. Это отчасти объясняет, почему его определение в тех же файлах, что и шаблон, является нормой. Из-за этого, во всех смыслах и целях, это также функция шаблона, отсюда и ее специализация. Если вы объявляете его вне тела шаблона, вам нужно рассматривать его как таковой.

person Hawkeye5450    schedule 10.03.2018
comment
Я знаю синтаксис самой функции; проблема не в этом; это касается использования их как друзей с шаблоном класса; размещение деклараций, определений и т. д. - person Francis Cugler; 10.03.2018
comment
Это объяснение помогает понять общий дизайн или порядок, в котором они должны быть. - person Francis Cugler; 10.03.2018