What is meant by non-member operator overloading - c++

I was recently going over an article on operator overloading in which it mentioned non-member operator overloading. I would appreciate it if someone could explain what is meant by non-member operator overloading with an example. I know what member operator overloading is (A method in a class which overloads an operator type (binary..etc) . I came across this post on SO which makes me believe that the purpose of non-member operator overloading is to handle operator overloading in which the first parameter is a not a class and is simply a native type. Any links or examples that explain what non-member operator overloading is would definitely be appreciated.

It means you can overload out-of-class:
struct X { int data; };
bool operator<(X const& a, X const& b)
{
return a.data < b.data;
}
This is useful for assymetrical overloading, where the left operand doesn't need to be your own type:
bool operator<(int a, X const& b)
{
return a < b.data;
}
A common idiom here is to combine it with in-class definition and friend declaration:
struct X
{
int data;
friend bool operator<(X const& a, X const& b) { return a.data<b.data; }
friend bool operator<(int a, X const& b) { return a<b.data; }
};
Here, operator< is still technically non-member.
Another useful side-effect of this, as pointed out by DrewDormann below, is that the (X const&, X const&) will apply to any operands that are implicitly convertible to X const&, not just expressions of that exact type.

the most common way is to overload operator<< that will be called on std::cout:
namespace X {
class MyClass {
...
};
}
std::ostream& operator<< (std::ostream&, const X::MyClass&);
this is called on std::ostream member so you don't define it inside your class.
however sometimes the functionality cannot be achieved via the public interfaces (because your operator needs access to data representation).

Related

overload greater than operator with or without friend

Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;

c++ less operator overload, which way to use?

For example: in a C++ header file, if I defined a struct Record and I would like to use it for possible sorting so that I want to overload the less operator. Here are three ways I noticed in various code. I roughly noticed that: if I'm going to put Record into a std::set, map, priority_queue, … containers, the version 2 works (probably version 3 as well); if I'm going to save Record into a vector<Record> v and then call make_heap(v.begin(), v.end()) etc.. then only version 1 works.
struct Record
{
char c;
int num;
//version 1
bool operator <(const Record& rhs)
{
return this->num>rhs.num;
}
//version 2
friend bool operator <(const Record& lhs, const Record& rhs) //friend claim has to be here
{
return lhs->num>rhs->num;
}
};
in the same header file for example:
//version 3
inline bool operator <(const Record& lhs, const Record& rhs)
{
return lhs->num>rhs->num;
}
Basically, I would like to throw the questions here to see if someone could come up with some summary what's the differences among these three methods and what are the right places for each version?
They are essentially the same, other than the first being non-const and allowing you to modify itself.
I prefer the second for 2 reasons:
It doesn't have to be a friend.
lhs does not have to be a Record
The best way to define the less operator is:
struct Record{
(...)
const bool operator < ( const Record &r ) const{
return ( num < r.num );
}
};
Welcome to c++20 where we have even more options.
//version 1
bool operator <(const Record& rhs)
{
return this->num>rhs.num;
}
this one is wrong, it should read:
//version 1
bool operator <(const Record& rhs)const
{
return this->num>rhs.num;
}
as you want the left hand side to be const-qualified as well.
//version 2
friend bool operator <(const Record& lhs, const Record& rhs) //friend claim has to be here
{
return lhs->num>rhs->num;
}
this one is symmetric. So suppose you have a struct Bar with an operator Record.
Then
Record rhs;
Bar lhs;
assert( lhs < bar );
the above works with a symmetric case, but not with a member function version.
The friend in class version is an operator that can only be found via Koenig lookup (Argument Dependent Lookup). This makes it very useful for when you want a symmetric operator (or one where the type is on the right, like ostream&<<*this) bound to a specific template class instance.
If it is outside of the class, it has to be template function, and a template function does overloading differently than a non-template function does; non-template functions permit conversion.
template<class T>
struct point {
T x ,y;
point operator-(point const& rhs)const{
return {x-rhs.x,y-rhs.y};
}
friend point operator+(point const& lhs, point const& rhs) {
return {lhs.x+rhs.x, lhs.y+rhs.y};
}
};
template<class T>
point<T> operator*( point<T> const& lhs, point<T> const& rhs ) {
return {lhs.x*rhs.x, lhs.y*rhs.y};
}
here - is asymmetric, so if we have a type that converts to a point<int> on the left, - won't be found.
+ is symmetric and a "Koenig operator", so it is a non-template operator.
* is symmetric, but is a template operator. If you have something that converts-to-point, it won't find the * overload, because deduction will fail.
//version 3
inline bool operator <(const Record& lhs, const Record& rhs)
{
return lhs->num>rhs->num;
}
this is similar to the template above, but here that problem doesn't occur. The difference here is that you can get the address of this function outside of the class, while the "koenig operator<" you wrote can only be found via ADL. Oh, and this isn't a friend.
c++17 adds in
auto operator<=>(const Record&)=default;
where we use the spaceship operator <=> to define ordering automatically.
This will use the ordering of both c and num to produce the required result.
Much like the rule of 5, you should seek to make =default here work correctly. Having state that < ignores is a bad smell, and so is entangling different parts of your state.
The non-member equivalent of your member function
bool operator <(const Record& rhs);
is
bool operator <(Record& lhs, const Record& rhs); // lhs is non-const
Now STL containers treat the items they store as const (at least as long as the comparison operator is concerned). So they call const-const variant of your operator. If they don't find it (in case you provided variant 1 only) - it is a compile error.
If you provide both const-const member and const-const non-member:
struct Record
{
bool operator <(const Record& rhs) const;
};
bool operator <(Record& lhs, const Record& rhs);
it is yet another compiler error because such definition leads to an ambiguity:
If two matches are found at the highest level where a match is found,
the call is rejected as ambiguous. /Stroustrup, C++, section 12.3.1/
Finally, (as noted in the previous answers) there's no need in the friend modifier since by default all fields of the struct are public.
PS make_heap doesn't expect the compared items to be const because it is a more low-level beast and using it you're kind of co-authoring a new heap-based library so it is your responsibility to track const-ness of items.
PPS set treatment of items as const does not protect you from modifying the keys of the items after they are inserted into the container - it will result in a runtime error (segfault) if you try it.
Favor in-class unless it cannot be in-class because first argument is the wrong type.

C++ how to write an operator that isn't a member function?

Anyone got an idea on how to write an operator for a class that isn't a member function of the class?
Just make it a free function, or a friend function. A good example of this is operator<<:
class X {
public:
int x;
}
ostream& operator<< (ostream& os, const X& x) {
os << x.x;
return os;
}
The benefit of making it a friend function is that you have direct access to private members, whereas a free function must access all members via public methods.
Arithmetic operators, stream operators, et cetera are often not members of a class. However, they may need to be friends in order to access private data members.
I prefer not to use friend and to expose methods that can be used by the operators instead. I believe this to be more in keeping with the Open/closed principle, as I could easily add a subtraction operator without editing the class.
These are handy for unit-testing, too (I can "inject" a std::ostringstream to test the output of print(), for instance).
Here is an example:
#include <iostream>
class Number
{
public:
Number(int j)
:i(j)
{
}
void print(std::ostream& os) const
{
os << i;
}
int value() const
{
return i;
}
private:
int i;
};
std::ostream& operator <<(std::ostream& os, const Number& n)
{
n.print(os);
return os;
}
Number operator +(const Number& n, const Number& o)
{
return Number(n.value() + o.value());
}
int main()
{
Number a(4), b(5), c(a + b);
std::cerr << c << std::endl;
}
Just declare the global function with the operator name:
Point operator+(Point& p, Vector& v) {
return new Point(p.x + q.i, p.y + q.j);
}
Basically, you can take the operator out of the class, and add a parameter to the beginning of the parameter list. In many cases, you will also need to declare the operator function as a friend.
For instance
class Foo
{
Foo operator +( Foo const& other );
};
becomes
class Foo
{
friend Foo operator +( Foo const&, Foo const& );
};
Foo operator +( Foo const& first, Foo const& second );
The friend statement allows the operator to still access any private or protected members needed.
Note that there are some restrictions on which operators can be overloaded in this manner. See this article for such a list.

operator overloading in c++

suppose i have 2 objects of a class and it has one int data member.
i want to add those integer data to other object and store the output in the first obj's data member.I can overload the + operator and use the statement like below
X+Y //where X and Y are objects of one class.
if i have to add like below
X+10// here i want to add 10 to the data member of X.
for above also i can overload the operator +.
but if i have 10+X and i want to add 10 to the data member of X how could i do it?
The same way:
MyClass operator+(MyClass const& lhs, MyClass const& rhs);
MyClass operator+(MyClass const& lhs, int rhs);
MyClass operator+(int lhs, MyClass const& rhs);
(operator+ should not normally be a member.)
If you overload operator+, you'll also want to overload +=. One
frequent idiom involved implementing + in terms of +=. This can
be more or less automated (if you have a lot of classes
supporting operators) by defining something like:
template<typename DerivedType>
class ArithmeticOperators
{
public:
friend DerivedType operator+(
DerivedType const& lhs,
DerivedType const& rhs)
{
DerivedType result(lhs);
result += rhs;
return result;
}
// And so on for the other operators...
protected:
~ArithmeticOperators() {}
};
template<typename DerivedType, typename OtherType>
class MixedArithmeticOperators
{
public:
friend DerivedType operator+(
DerivedType const& lhs,
OtherType const& rhs)
{
DerivedType result(lhs);
result += rhs;
return result;
}
friend DerivedType operator+(
OtherType const& lhs,
DerivedType const& rhs)
{
DerivedType result(rhs);
result += lsh;
return result;
}
// And so on: non-commutative operators only have the
// first.
protected:
~MixedArithmeticOperators() {}
};
, then deriving from whatever is needed: in your case:
class MyClass : public ArithmeticOperators<MyClass>,
MixedArithmeticOperators<MyClass, int>
You have to create an overloaded operator as a free function with the correct parameter order:
// This will match "int + YourClass" additions
YourClass operator+(int Left, const YourClass & Right)
{
// If your addition operation is commutative, you can just call the other
// version swapping the arguments, otherwise put here your addition logic
return Right + Left;
}
If the operator needs to fiddle with the internals of your class you can make it friend.
As others pointed out, there are some best/common practices that you should follow if you implement operator+, I suggest you to have a look to the great C++-FAQ on operator overloading for more info about them.
Don't overload the operator + as a member function of the class.
You can either define a global function operator + with two parameters or make operator + a friend of your class (In that case you should be having a parameterized constructor to convert 10 to an object of your class-type).
Define a non-member stand-alone free function as:
sample operator+(int leftOperand, const sample & rightOperand)
{
//...
}
Although you can do that using a global operator+, I would advise not to do it.
Only use operator overloading for data types for which the operators are immediately clear, e.g.:
complex numbers
strings (+,- ok, but * probably doesn't make much sense here)
The risk with overloaded operators is that the compiler may perform unwanted conversions, especially if you didn't make the single-argument constructor explicit.
You should define a non-member friend function
YourClass operator+(const YourClass &a, const YourClass&b) {
// do the math here
}
it should be friend to get to the private members of YourClass. Also you should create constructor for YourClass that takes int.
In this way you've got one operator+ and for every other then int you just create another constructor.

Overloading assignment operator

We can overload assignment operator as a normal function, but we cannot overload assignment operator as a friend function. Why?
Because the C++ Standard says so, Article 13.5.3/1:
An assignment operator shall be
implemented by a non-static member
function with exactly one parameter.
Because a copy assignment operator
operator= is implicitly declared for a
class if not declared by the user
(12.8), a base class assignment
operator is always hidden by the copy
assignment operator of the derived
class.
That's all you really need to know. A friend function is not a member function, so it cannot be used to overload the assignment operator.
If you would like to write:
MyClassObject = MyFriendObject;
Then you would want to implement a constructor that takes a const reference to the friend class as it's parameter.
The difference between overloading by friend function and overloading by member function is that the calling object must be the first operand in overloading by member function, while there is no restriction in overloading by friend function. This is the reason behind the standard. Similarly, some other operators requiring the first operand to be the calling function must be overloaded using member functions (examples: =, [], ->, and ( )).
You cannot "extend" the assignment operator with a "free function" outside the class, but you can design the class so it will allow it:
Data.h
class Data {
public:
Data& operator=(const Data& lhs) { /*...*/; return *this; }
template <typename T> Data& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
private:
// ...
};
Point.h
class Point {
public:
float x,y;
Point& operator=(const Point& lhs) { x = lhs.x, y = lhs.y; return *this; }
template <typename T> Point& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
};
Assignment.h
Data& assign(const Data& lhs, const Point& rhs) {
lhs["x"] = rhs.x;
lhs["y"] = rhs.y;
return lhs;
}
Point& assign(const Point& lhs, const Data& rhs) {
rhs.query("x", lhs.x) || rhs.query(0, lhs.x);
rhs.query("y", lhs.y) || rhs.query(1, lhs.y);
return lhs;
}