The answer to this question seems to escape me, but how do you go about overloading with non-member functions. Do you just create a program level function and where ever the prototype (or definition) exists the operator is overloaded for that class type?
With a member function, this would be the left hand side parameter, meaning your operator would only have one argument (or none for unary operators). With a freestanding function, you must supply either two or one arguments for binary or unary operators, respectively.
A good example is the << operator for streams:
class T;
// ...
std::ostream & operator<<(std::ostream &os, const T &val)
{
// ...
return os;
}
Here, os is the left hand side parameter, and val is the right hand side one.
As for "where", the operator must be defined where you use it. Generally, put them at the same place as the type you're overloading the operators for.
EDIT:
For non trivial operators (arithmetic operations on primitive types), operators are syntactic sugar for function calls. When you do this:
std::cout << "Hello";
It's like writing that:
operator<<(std::cout, "Hello");
But more readable.
For member operators, the left parameter will be this (and that's why member operators have one less argument).
Related
This question gives a good answer why to define operator overloads as non-members: Operator overloading : member function vs. non-member function?
If you define your operator overloaded function as member function,
then compiler translates expressions like s1 + s2 into
s1.operator+(s2). That means, the operator overloaded member function
gets invoked on the first operand. That is how member functions work!
But what if the first operand is not a class? There's a major problem
if we want to overload an operator where the first operand is not a
class type, rather say double. So you cannot write like this 10.0 +
s2. However, you can write operator overloaded member function for
expressions like s1 + 10.0.
Now I have a situation where I need to overload operator==. In my case, only (a) objects of (b) the same type will be compared.
Is there a reason to still define operator== as a non-member or should I implement it as a member in that case?
Because operator== has symmetric semantics for its LHS and RHS argument, the recommended approach is to always implement it as a non-member in terms of the public interface of its operands (or if private data is required, to declare it as a friend inside the class).
So
class Bla
{
public:
// complete interface to data required for comparison
auto first();
auto second();
// ... more
private:
// data goes here
};
bool operator==(Bla const& L, Bla const& R)
{
return
std::forward_as_tuple(L.first(), L.second() /*, ... */) ==
std::forward_as_tuple(R.first(), R.second() /*, ... */)
;
}
This way, implicit conversion to Bla are considered for both the L and R arguments (I'm not saying implicit conversions are a good idea, but if you have those, it's better to avoid surprises where they are only considered for the RHS argument).
This is related to the difference-between-cout-x-and-cout-operator-x question, but still a little different...
#include <iostream>
int main(){
std::cout << "hello" << std::endl;
std::cout.operator<<("hello2");
std::cout.operator<<(std::endl);
operator<<(std::cout, "hello3");
// operator<<(std::cout, std::endl);
return 0;
}
Q1: Why does std::cout.operator<<("hello2"); work?
From other answers on SO I would expect the compiler to complain since operator<< is meant to be a free function and not a member of cout. On my system, however, it prints "0x10d54df31". And, stranger yet, the following line correctly correctly executes std::endl.
Q2: Why does operator<<(std::cout, std::endl); not work?
I know that std::endl is a function, but it seems strange (to me) that the hello3 output works whilst the `std::endl' doesn't. Instead the compiler throws an error:
main.cpp:10:4: error: no matching function for call to 'operator<<'
operator<<(std::cout, std::endl);
Q3: How can the first std::cout << "hello1" << std::endl; be written in operator<<(...) form?
If the first two questions have been answered, then this has probably already covered. It's the point of this learning exercise, so seems sensible to ask it explicitly.
Operators can be implemented in different ways, in particular an operator<< for which the left hand side is your type can be implemented as either a free function or as a member function of that left hand side type.
While you must implement ostream& operator<<(ostream&, MyType const&) as a free function (since MyType is not the left hand side), the library implementation can choose* to implement operator<< for some fundamental types insde the std::ostream type (which is really a particular instantiation of a template, I am trying to ignore the details).
Edit: After checking with the standard this is incorrect:
This is what you are noticing in the code, the overload that takes a const char* is implemented as a member of ostream (basic_ostream<char,char_traits<char>).
The overloads taking manipulators are implemented as member functions (Q2), and there is an implicit conversion from const char* to const void* that will be picked if you use the syntax for explicitly calling a member operator (Q1). For Q3, the answer would be:
operator<<(std::cout, "Hello").operator<<(std::endl);
* The implementation is actually not free to choose, since the standard mandates the signatures.
Some overloads of operator<< are class members, others are not.
In C++03 this created some baffling call scenarios since a reference to non-const (argument of the not-member) can't be bound to an rvalue, but in C++11 at least one such has been fixed by introducing an rvalue reference argument overload.
So, which calls compile or not depends more in general also on the C++ standards version, C++03 or C++11.
There is a bunch of member output operators defined in std::ostream. In retrospect that was probably an error but when IOStreams were first created I think it was actually necessary. These member operators include the overloads taking function pointers which means you'll need to use member notation for those. The operators using C-strings are non-member overloads, i.e., you need to use the non-member function call notation to get the C-string overload. When you call the member operator with a char const* the char const* will be converted to void const* for which there is a member output operator.
Your questions can be broken down to member functions an non-member functions.
Having 13.5.2 Binary operators
A binary operator shall be implemented
either by a non-static member function (9.3) with one parameter or by
a non-member function with two parameters. Thus, for any binary
operator #, x#y can be interpreted as either x.operator#(y) or
operator#(x,y). If both forms of the operator function have been
declared, the rules in 13.3.1.2 determine which, if any,
interpretation is used.
Omitting a quote of 13.3.1.2 the member function (operator) is preferred.
The line 'std::cout << "hello" << std::endl;' involves non member functions. Each 'std::cout.operator' is an explicit member function call.
Q1 is the member operator<<(const void*)
Q2 there is no member taking a function
Q3 It is not possible
I wonder about the multiply operation(*) is overloading in pointer or vice versa?
Or the operators are individual?
C++
They are separate operators, and which one you overload depends on what parameters you pass to the operator.
struct A
{
//dereference operator
A /*or whatever*/ operator *() { /*...*/ };
//multiply operator
A operator *(const A&) { /*...*/ };
};
//...
A a;
*a; //calls dereference operator
a * a; //calls multiply operator
It works exactly like all of the operator symbols which can define a
unary or a binary operator (+, - and & are the other ones), it
depends on the number of arguments the function will take. Thus, a
unary * should be defined to take a single operator, either as a
non-static class member taking no arguments (other than this), or as a
free function taking a single argument. The binary operator should be
defined to take two arguments, either as a non-static class member
taking one argument (in addition to this), or a free function taking
two arguments.
Note that the names of the functions are considered the same, so a
binary version can hide a unary one, or vice versa.
I am currently creating a utility class that will have overloaded operators in it. What are the pros and cons of either making them member or non-member (friend) functions? Or does it matter at all? Maybe there is a best practice for this?
I'd go with "C++ Coding Standards: 101 Rules, Guidelines, and Best Practices": if you can do it as non-member function, do it as non-member function (in the same namespace).
One of the reasons: it works better with implicit type conversion. An Example: You have a complex class with an overloaded operator*. If you want to write 2.0 * aComplexNumber, you need the operator* to be a non-member function.
Another reason: less coupling. Non-member-functions a less closely coupled than member functions. This is almost always a good thing.
Each operator has its own considerations. For example, the << operator (when used for stream output, not bit shifting) gets an ostream as its first parameter, so it can't be a member of your class. If you're implementing the addition operator, you'll probably want to benefit from automatic type conversions on both sides, therefore you'll go with a non-member as well, etc...
As for allowing specialization through inheritance, a common pattern is to implement a non-member operator in terms of a virtual member function (e.g. operator<< calls a virtual function print() on the object being passed).
If you plan on implementing streaming operators (<< and >>) then they will be non-members methods because your object is on the left of the operator.
If you plan on implementing ->, () or [] they are naturally member methods.
For the others (comparison and mathematical) you should check out Boost.Operators, it really helps.
For example, if you want to implement the following operators:
MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);
You only have to write:
class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
MyClass& operator+=(int);
private:
};
The 2 operator+ will be automatically generated as non-members which will let you benefit from automatic conversions. And they will be implemented efficiently in term of operator+= so you write code only once.
For binary operators, one limitation of member functions is that the left object must be of your class type. This can limit using the operator symmetrically.
Consider a simple string class:
class str
{
public:
str(const char *);
str(const str &other);
};
If you implement operator+ as a member function, while str("1") + "2" will compile, "1" + str("2") will not compile.
But if you implement operator+ as a non-member function, then both of those statements will be legal.
If you are implementing op, then most probably you need to implement op=. i.e. if you are overloading + operator, then you should implement +=.
Make sure that you are returning const to an object if you are doing post-increment or overloading + operator.
So, if you overload operator + , then implement it as a non-member operator and use += operator inside it. For eg.
const A operator+(const A& lhs, const A& rhs)
{
A ret(lhs);
ret += rhs;
return ret;
}
There is nothing like best practices but it depends on the operator you are overloading ..
For e.g .
>> and << can't be overloaded as member functions .
Suppose you want to do like this : obj1 = 2 * obj2 then go for non-member function.
For binary operator overloading member function takes only 1 parameter (invoking object is impcliitly passed ) whereas non-member function takes 2 parameters .
Why is that sometimes an operator override is defined as a method in the class, like
MyClass& MyClass::operatorFoo(MyClass& other) { .... return this; };
and sometimes it's a separate function, like
MyClass& operatorFoo(MyClass& first, MyClass& bar)
Are they equivalent? What rules govern when you do it one way and when you do it the other?
If you want to be able to do something like 3 + obj you have to define a free (non-member) operator.
If you want to make your operators protected or private, you have to make them methods.
Some operators cannot be free functions, e.g., operator->.
This is already answered here:
difference between global operator and member operator
If you have a binary operator like +, you normally want type conversions to be performed on both operands. For example, a string concatenation operator needs to be able to convert either or both of its operands from a char * to a string. If that is the case, then it cannot be a member function, as the left hand operand would be *this, and would not have a conversion performed.
E.g.:
operator+( a, b ); // conversions performed on a and b
a->operator+( b ); // conversion can only be performed on b
If the operator is defined outside of a class it's considered global, and allows you to have other types appear on the left hand side of the operator.
For example, given a class Foo, with a global operator + you could do:
Foo f;
Foo f2 = 55 + f;