Это всего лишь предупреждение о сложном аспекте языка.Когда вы объявляете функцию friend
, она не является членом класса, в котором находится объявление. Вы можете определить его там для удобства, но на самом деле он принадлежит пространству имен.
Объявление функции-друга, которая являетсяне шаблон, внутри шаблона класса, все еще объявляет не шаблонную функцию в пространстве имен.Он не является ни членом класса, ни самим шаблоном.Тем не менее, генерируется шаблоном класса.
Генерация не шаблонных функций из шаблона немного мутная.Например, вы не можете добавить объявление для этой функции за пределами блока class
.Поэтому вы также должны определить его внутри блока class
, что имеет смысл, потому что шаблон класса сгенерирует его.
Еще одна хитрость в друзьях заключается в том, что объявление внутри class Float {}
не объявляет функцию впространство имен.Вы можете найти его только через зависящее от аргумента значение разрешения перегрузки, то есть, указав, что аргумент имеет тип Float
(или ссылку, или указатель).Это не проблема для operator+
, так как в любом случае она может быть перегружена и никогда не будет вызываться, за исключением пользовательских типов.
Для примера потенциальной проблемы представьте, что у вас естьконструктор преобразования Float::Float( Bignum const& )
.Но Bignum
не имеет operator+
.(Извините, надуманный пример.) Вы хотите положиться на operator+(Float const&, Float const&)
для добавления Bignum
.Теперь my_bignum + 3
не будет компилироваться, поскольку ни один из операндов не является Float
, поэтому он не может найти функцию friend
.
Возможно, вам не о чем беспокоиться, если рассматриваемая функция является operator
.
Или вы можете изменить friend
на шаблон.В этом случае он должен быть определен вне блока class {}
и объявлен перед ним, вместо того, чтобы быть объявленным и определенным внутри .
template<int E, int F> // now this is a template!
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
template<int E, int F>
class Float
{
// deduce arguments E and F - this names operator+< E, F >.
friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs);
};