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.
This is quite an old topic but I think the easiest way to declare the operator is to define it inside Float class.
The syntax is easier to write and understand and it will work exactly the same (except that it will be inlined), it will no be a member function.
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 theclass
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 typeFloat
(or a reference or pointer). This is not an issue foroperator+
, 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& )
. ButBignum
does not haveoperator+
. (Sorry, contrived example.) You want to rely onoperator+(Float const&, Float const&)
forBignum
addition. Nowmy_bignum + 3
will not compile because neither operand is aFloat
so it cannot find thefriend
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 theclass {}
block, and declared before it, instead of needing to be declared and defined inside.You need to do exactly as the warnings say:
This declares a full specialization of the operator template a friend of a specific instance of the class template. In a comment to the question UncleBens has kindly provided a link to an explanation why that is so complicated.