Reputation: 9090
Is it considered a good practice to use friend
to define global functions within the class definition, even when the access to private members is not needed. For example
template<typename T>
class A {
public:
A(T v);
T value() const;
friend A operator+(T n, const A& a) {
return A(a.value() + n);
}
};
instead of
template<typename T>
class A {
public:
A(T v);
T value() const;
};
template<typename T>
A<T> operator+(T n, const A<T>& a) {
return A<T>(a.value() + n);
}
even though operator+
only uses value()
which is public.
Is this commonly done, us is it not recommended?
Upvotes: 3
Views: 98
Reputation: 302892
There's one major advantage to friend
here. When we define:
friend A operator+(T, const A&);
This is not a function template. This is just a function - a special one that can only be found by ADL. But since it's not a function template, conversions still can happen. On the flip side:
template <class T>
A<T> operator+(T, const A<T>&)
is a normal old function template with all of the normal rules regarding template type deduction.
Why does this matter? Consider:
A<double> a(4.2);
5 + a;
In the first case, this is perfectly fine. We find operator+(double, const A<double>&)
, the 5
gets converted to 5.0
, which is an allowed conversion, and we get back A<double>(9.2)
.
In the second case, template deduction fails because the T
deduces to different types for the two arguments. Hence, the code is ill-formed.
Upvotes: 4