Why is it possible to place friend function definitions inside of a class definition?
Asked Answered
T

6

36

Is it not supposed for a friend function to be explicitly defined outside of a class ?
If so why can i declare a friend function inside a class definition just like any member function ?
What is this ?
Is it only OK with some operators such as < operator or is it applicable to all operators?
If it is applicable to all of them, Is there any disadvantage for doing this ?
Should it be avoided? If so why ?

class person 
{
public:
    bool operator<(int num)
    {
        return  x < num ? true : false ;
    }
    bool operator<(person& p)
    {
        return  x < p.x ? true : false ;
    }

    friend bool operator<(int num, person &p)
    {
        return  p.x < num ? true : false ;
    }

    void setX(int num)
    {
        x = num;
    }

private:
    int x;


};

Update:
I am not asking for choosing non-member operator overloading or member operator overloading.
What i want to know is that :
Why we are permitted to move the definition of friend methods inside our class definition?.
Is it not violating any things? If it is not, Why would we have friends in first place?
We could simply define overloads as member functions ( I know the limitations of member functions ) But i am saying knowing this, Why isn't compiler complaining that I haven't defined friend function outside a class definition since it doesn't need to be inside of it (because of the class parameter it has) So why are we allowed to define a friend function inside a class definition?

Teliospore answered 7/7, 2013 at 13:25 Comment(4)
If you are asking about the definition of the friend function, then you should change the title of your question to reflect that.Rwanda
what should i write then?Teliospore
You can do it because the standard explicitly allows it. As for the reason why the standard allows it -- my guess is that it was considered convenient enough to be worth it.Louvenialouver
You can ask "why is it possible to place friend function definitions inside of a class definition?"Rwanda
C
15

Is it not supposed for a friend function to be explicitly defined outside of a class ?

Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions, and like member inline functions they behave as though they were defined immediately after all class members have been seen but before the class scope is closed (the end of the class declaration). Friend functions that are defined inside class declarations are in the scope of the enclosing class. quote

Is it only OK with some operators such as < operator or is it applicable to all operators?

It is best to try to avoid friend functions since they are opposite to what you are trying to do using a private class scope and mainly "hide" the variables. If all your functions are friend functions then what is the use of having private variables?

Still, there are some common operators which are often declared as friend functions, those are operator<< and operator>>

Carthusian answered 7/7, 2013 at 13:44 Comment(6)
Thank you very much :) I am not trying to declare all of my needed functions as friends, I was curios to know why a friend function (which is solely used for operating overloading and nothing else) can be defined inside a class and why it is permittedTeliospore
@Teliospore the quote I gave you doesn't atually say "why it is permited" but explains why "it is not not permited".Carthusian
i know , but the part "Friend functions can be defined inside class declarations" , says we are premitted to do so, i understand that friend functions are not an answer for everything as you have also clearly mentioned , when i was saying that , i meant the quoted section which kinda cleared parts of my questionTeliospore
They are "in file scope"? Shouldn't they be inserted into the surrounding scope, be it file, namespace, function, class?Roguish
Friend functions that are defined inside class declarations are in the scope of the enclosing class. Not sure this part is accurate. At least I can't spot any difference between friend functions defined inside of a class declaration and outside of it - both act as free functions without extra scope restriction.Audriaaudrie
@TheDreamsWind Good point. Both are kinda true, actually... The trick is ADL. If the friend function has an argument of the class type enclosing it, then the proper scope will be resolved at an unqualified call site outside the class. OTOH, if it doesn't (e.g. friend void f() {}, then the compilation will fail with f being undeclared.Eimile
T
7

Alexandru Barbarosie answer is correct. It means that we can declare a friend function, which is not a member function, within a class. This can be nice to organize the code. I think an example can help to understand it in case it isn't clear.

#include <iostream>

class A {
    public:
        A(int val) : val(val) {}
        // The following isn't a member function, it is a friend 
        // function declared inside the class and it has file scope
        friend void draw (A &a) {
            std::cout << "val: " << a.val << "\n";
        }
    private:
        int val;
};

int main() {
    A a(5);
    draw(a); // outputs "val: 5"
    //A::draw(a); // Error: 'draw' is not a member of 'A'
}
Triley answered 6/3, 2018 at 12:47 Comment(0)
T
4

Because an operator needs to know details of the right-hand side of the expression in which is used, if it must access private data of the type which resides on that side, it needs to be friend with that class.

If you are trying to compare an int with a person, like in your example, choices are two:

  • you provide an implicit conversion from person to int so that < can use it without accessing any private field.
  • or you declare the operator as friend of person so that it can access x in the right-hand side of the comparison.
Tryout answered 7/7, 2013 at 13:28 Comment(5)
That would still be possible if only the friend declaration was inside the class definition, with the friend function definition kept outside of it.Interlinear
Thanks, But i didn't why we use friends, I asked why we are permitted to move the definition of friend methods inside our class definition. Is it not violating any things? If it is not, Why would we have friends in first place, We could simply define overloads as member functions ( I know the limitations of member functions ) but i am saying knowing this , why isn't compiler complaining that i haven't defined friend function outside a class definition since it doesnt need to be inside of it (because of the class parameter it has)Teliospore
I suggest you to take a look here: https://mcmap.net/q/15363/-what-are-the-basic-rules-and-idioms-for-operator-overloading/…Tryout
@Teliospore obviously it is not "violating any things". Otherwise you couldn't even ask the question, because it wouldn't compile.Rwanda
by violating i meant any thing such as good practice or the likesTeliospore
B
4

If you are creating a header-only class (which makes deployment vastly easier) then defining a friend function within the class is the only way to go since definitions can only appear in a single translation unit. The normal technique of include guards doesn't work since that only handles things like recursive inclusion.

This can be a big deal if you are trying to write standards-conformant code. For example, to implement the RandomNumberEngine named requirement from the C++ normative standard, it is necessary to provide operator<<. This has to be a friend to take a std::ostream& object as its first parameter (otherwise it will look like a normal, single parameter member function operator overload). Ordinarily the friend declaration would go in the class definition and and the function definition in a separate .cpp source file. But if you want a header-only implementation, it must be defined in the class to avoid multiple definition errors.

Bonspiel answered 24/10, 2019 at 19:23 Comment(2)
"defining a friend function within the class is the only way to go" One could also use inline functions.Canaliculus
@Canaliculus true, up to a point. However I'm not happy about doing this since inlines with non-static linkage do not need to be the same across translation units, and that's just asking for trouble. For an operator, it makes sense to keep the definition as closely associated with its class as possible.Bonspiel
S
2

As Jack mentioned friend functions are required in places where access to private data is needed. There is also another purpose. This is related to types of inheritance. Only derived class and its friends can convert pointer to a private base to a derived type. So you might sometimes want to make some function a friend of derived class to allow this inside function body.

Singlehearted answered 7/7, 2013 at 13:36 Comment(0)
S
0

Another use for placing friend function definition inside a class is to implement the hidden friend idiom.

E.g., the following code from Argument dependent look-up and the hidden friend idiom by Rainer Grimm.

// hiddenFriend.cpp

#include <iostream>

class MyDistance{
 public:
    explicit MyDistance(double i):m(i){}

    friend MyDistance operator+(const MyDistance& a, const MyDistance& b){         // (1)
        return MyDistance(a.m + b.m);
    }
    
    friend MyDistance operator-(const MyDistance& a, const MyDistance& b){         // (2)
        return MyDistance(a.m - b.m);
    }

    friend std::ostream& operator<<(std::ostream &out, const MyDistance& myDist){  // (3)
        out << myDist.m << " m";
        return out;
    }
    
 private:
    double m;

};


int main() {

    std::cout << '\n';

    std::cout << "MyDistance(5.5) + MyDistance(5.5): " << MyDistance(5.5) + MyDistance(5.5) << '\n';  // (4)

    std::cout << "MyDistance(5.5) - MyDistance(5.5): " << MyDistance(5.5) - MyDistance(5.5) << '\n';  // (5)

    std::cout << '\n';

}

Since the scope of the friend functions is within the class in which they are defined, the correct operator+, operator- and operator<< are picked-up because of ADL.

This idiom is also very useful in the context of class templates to generate appropriate friend functions based on the template arguments.

Svelte answered 29/1 at 16:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.