Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator overloading inside vs outside class [duplicate]

What is the difference between inside and outside class overloading?

class A{
    public:
       bool operator==(const A *i){
         ....
         ....
       }
 };

vs

 bool operator==(const A *i , const A *j){
   ....
   .... 
 }
like image 660
Michael Oks Avatar asked Jan 10 '17 07:01

Michael Oks


1 Answers

First consider this example using your class (reformatted to a style I prefer):

class A
{
public:
    auto operator==( A const* p )
        -> bool
    {
        return true;        // Whatever.
    }
};

auto main()
    -> int
{
    A u{}, v{};
    A const c{};

    bool const r1 = (u == &v);  // OK but needlessly annoying.
    bool const r2 = (c == &v);  // !Will not compile. 
}

Here

  • Since the argument is a pointer, the client code must apply &.
  • Since the method is not const, objects that are const can not be compared.

The conventional way to do this is therefore to pass the argument by reference, and to make the method const:

class B
{
public:
    auto operator==( B const& o ) const
        -> bool
    {
        return true;        // Whatever.
    }
};

auto main()
    -> int
{
    B u{}, v{};
    B const c{};

    bool const r1 = (u == v);   // OK.
    bool const r2 = (c == v);   // OK.
}

If you define the comparison outside the class, like this:

class B
{};

auto operator==( B const& u, B const& v )
    -> bool
{
    return true;        // Whatever.
}

auto main()
    -> int
{
    B u{}, v{};
    B const c{};

    bool const r1 = (u == v);   // OK.
    bool const r2 = (c == v);   // OK.
}

… then

  • The definition guaranteed does not depend on internal implementation details of class B, that conceivably could change in the future.
  • Also the first argument can be a value that converts implicitly to B.
  • You can, if you want, have formal arguments of different types, where the class only appears in the second argument, like this:
auto operator==( int const u, B const& v )
    -> bool
{
    return true;        // Whatever.
}

If you choose to place these non-member operators inline inside the class definition, via the friend mechanism (so that they're found via ADL lookup), then you lose the first bullet point's advantage, but you then have all the code relevant for use of the class, within the class definition:

class B
{
public:
    friend
    auto operator==( B const& u, B const& v )
        -> bool
    {
        return true;        // Whatever.
    }

    friend
    auto operator==( int const u, B const& v )
        -> bool
    {
        return true;        // Whatever.
    }
};

auto main()
    -> int
{
    B u{}, v{};
    B const c{};

    bool const r1 = (u == v);   // OK.
    bool const r2 = (c == v);   // OK.
    bool const r3 = (42 == v);  // OK.
}
like image 79
Cheers and hth. - Alf Avatar answered Oct 26 '22 23:10

Cheers and hth. - Alf