tmlen
tmlen

Reputation: 9090

Using friend to reduce verbosity

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

Answers (1)

Barry
Barry

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

Related Questions