What is wrong with my code?
template<int E, int F>
class Float
{
friend Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
G++ just keeps warning:
float.h:7: warning: friend declaration ‘Float<E, F> operator+(const Float<E, F>&, const Float<E, F>&)’ declares a non-template function
float.h:7: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
I tried to add <> after the function name here
as mentioned in the warning note, but g++ gives me an error.
I compiled the code with clang++, it was fine, no warning at all.
It's just a warning about a tricky aspect of the language. When you declare a friend
function, it is not a member of the class the declaration is in. You can define it there for convenience, but it actually belongs to the namespace.
Declaring a friend function which is not a template, inside a class template, still declares a non-template function in the namespace. It is neither a member of the class, nor itself a template. However, it is generated by the class template.
Generating non-template functions from a template is a bit hazy. For example, you cannot add a declaration for that function outside the class
block. Therefore you must define it inside the class
block as well, which makes sense because the class template will generate it.
Another tricky thing about friends is that the declaration inside class Float {}
does not declare the function in the namespace. You can only find it through argument-dependent meaning overload resolution, i.e. specifying an that an argument has type Float
(or a reference or pointer). This is not an issue for operator+
, as it is likely to be overloaded anyway, and it will never be called except for with user-defined types.
For an example of a potential issue, imagine you have a conversion constructor Float::Float( Bignum const& )
. But Bignum
does not have operator+
. (Sorry, contrived example.) You want to rely on operator+(Float const&, Float const&)
for Bignum
addition. Now my_bignum + 3
will not compile because neither operand is a Float
so it cannot find the friend
function.
Probably, you have nothing to worry about, as long as the function in question is an operator
.
Or, you can change the friend
to be a template as well. In that case, it must be defined outside the class {}
block, and declared before it, instead of needing to be declared and defined inside.
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);
};