I'm learning about Operator Overloading at the moment on learncpp.com and came across a statement that I can't quite wrap my head around. Here it is:
When dealing with binary operators that do modify the left operand
(e.g. operator+=), the member function version is typically preferred.
In these cases, the leftmost operand will always be a class type, and having the object being modified become the one pointed to by
*this is natural. Because the rightmost operand becomes an explicit parameter, there’s no confusion over who is getting modified and who
is getting evaluated.
I don't understand why the left hand operand will always be a class type. If I were overloading +=, for example, why couldn't I overload with the user defined class as the righthand parameter, like below?
void operator+=(int blah, MyNewClass foo);
Thanks in advance!
Despite the comments, you read this correctly: it’s talking about all such modifying operators, and it’s using the statement about the left-hand operand to justify the idea of a member function being “typically preferred”. (If it’s going to be a class-type object, you definitely have the opportunity to use a member function, and we generally prefer to express modifications to such objects in terms of member functions.)
The passage simply doesn’t consider the esoteric possibilities of overloading with non-member functions:
enum nil {};
// Use left-to-right compound assignment:
void operator+=(const int &i,nil &n)
{n=static_cast<nil>(n+i);}
// Make something into a pointer (*):
template<class T>
void* operator*=(T &t,nil) {return &t;}
struct A {operator int();};
// Convert sum to a percentage (%):
double operator%=(A a,A b) {return (a+b)/100.;}
// Infix call notation (like $ in Haskell):
template<class R>
R operator&=(R f(int),A a) {return f(a);}
Very occasionally someone might find a clever way of using, say, >>= in this fashion to emulate Haskell, but for someone just learning the language (to whom that passage is certainly addressed), perhaps the very possibility of such examples is best left unsaid. (Forget I said anything.)
Related
This feels like too basic a question to not have asked already so if it's already out there I'd accept the link as the answer or delete this post if you fellas see fit, personally I couldn't find it anywhere at least so perhaps this'll be useful to others...
So yeah, like it's said in the title, how do I make operators that'd let me work from the left side of the object? f.e:
++obj
variable * obj
etc
If I wanted to work on the right side of that 'obj' I'd make something like
obj operator*(const variable &t){...} //for obj * variable operation
intuitively I tried
obj *operator(const variable &t){...} //for variable * obj operation(?)
to make it work the other way around but of course, that didn't work, any suggestions?
Ummm you cannot do that. I mean, choose which side the operator works on. It is defined by the standard. The operators in c++ do not have sides they operate on. All are different operators. The operator you overload is defined by the signature.
The "side" has meaning only for the unary operators anyway. For binary operators it is either a member function called on the left operand, with right operand passed as an argument, or a free standing function.
The case that "allows definition of the side" is ++ and --. And it is a special case. ++c and c++ are actually two different operators in terms of language -- pre- and post- incrementation. The differentiation between realized by a "bogus" parameter in the overload: http://en.cppreference.com/w/cpp/language/operator_incdec.
There are other unary operators too, and you cannot choose side E.g: !, ~, there are no suitable overloads defined for "right side" cases.
Other disambiguation is also done via parameters. * used for both, member access and arithmetic operation. The operator which you overload is defined by number of parameters.
T T::operator*(const T2 &b) const; is artithmetic one, and R& T::operator*(); is member access.
Here you can find rules for all operators: http://en.cppreference.com/w/cpp/language/operators.
Aaand since its c++ you can abuse it. Unrecommended though.
You can overload function and make that function friend of the class.
variable operator*(const variable &, const variable *);
class variable {
friend variable operator*(const variable &, const variable *);
};
I have a function multiply and a function sum, with special characteristics, implemented on a given class i.e. (EngineManager). These functions add and multiply integers in a special fashion and they give away as a result a different class i.e. (StandardShare). When I try to implement the overload directly, the compiler promts:
Overloaded 'operator+' must be a unary or binary operator (has 3 parameters)
I understand that the third parameter it is referring to is the this pointer. But as I cannot implement them as free methods, given that they use functions from the hos class i.e. (EngineManager), what alternative do i have.
The code should look like this:
class EngineManager {
public function Shares::StandardShare* addShares(int a, int b){
//Does Something......
};
inline Shares::StandardShare* operator +(int a, int b){
return this->addShares(a,b);
};
};
Thanks in advance
This is neither possible, nor a good idea.
It's not possible not only because overloading the + operator that takes two arguments must be a free function, but also because the type of both arguments cannot be a simple built-in type (like int). At least of them must be a class or enumerator type.
It's not a good idea because, even if it were possible, the effect of this would not be confined to the class. The overloaded operator would be called everywhere where you include the header file of your class. So suddenly all integer additions across your program would break. But most importantly, it's not a good idea because it breaks the intuitive meaning of using the + operators with two integers. If you change that meaning, you're only creating confusion for no good reason.
Was the unary + operator only included for symmetry with the unary - operator, or does it find some practical use in C++ code?
Searching here, I came across What is the purpose of the unary '+' operator in C?, but the only useful scenarios there involve preprocessor macros. Those are good to know, but they seem to be some less common situations, and involve macros. Are there any use cases involving more common C++ code?
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';
The first insertion writes the character a to cout. The second insertion writes the numeric value of ch to cout. But that's a bit obscure; it relies on the compiler applying integral promotions for the + operator.
Symmetry with unary - isn't entirely useless; it can be used for emphasis:
const int foo = -1;
const int bar = +1;
And an overloaded unary + can be used to denote an operation that yields the same logical value as its operand, while performing some non-trivial computation. (I've seen this done for type conversions in Ada, which permits unary +, but not conversions, to be overloaded.) I don't have a good C++ example to hand, and one could argue that it would be poor style. (Then again, I've seen plenty of rants about overloading <<.)
As for why C++ has it, it's probably largely for consistency with C, which added it with the 1989 ANSI standard. The C Rationale just says:
Unary plus was adopted by the C89 Committee from several
implementations, for symmetry with unary minus.
If you explicitly stay clear of any number value semantics for a class, any operator overloading is clear not to "do as the ints do". In that case, the unary plus may get any meaning, doing much more than just returning *this
Prominent example: Boost.Spirit's unary plus for the embedded EBNF's Kleene Plus generates a parser rule that lets it's argument (a parser rule as well) match one or more times.
The unary + operator turns a lvalue into an rvalue:
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
Oh noes! This code won't link, because someone forgot to define (as well as declare) A::value. std::min takes its arguments by reference so A::value must have an address so a reference can bind to it (technically, the one definition rule says it must be defined exactly once in the program.)
Nevermind, unary plus to the rescue:
int x = std::min(0, +A::value);
The unary plus creates a temporary with the same value, and the reference binds to the temporary, so we can work around the missing definition.
This isn't something you need often, but it is a practical use of the unary plus operator.
Unary + applies integral promotions. #PeteBecker's answer shows one way that can be useful.
For another, note that an unscoped enumeration type gets promoted to an integer type which can represent all values in the enum. So in C++03, even without C++11's std::underlying_type<T>, you could do:
enum MyBitMask {
Flag1 = 0x1,
Flag2 = 0x2,
Flag3 = 0x4,
Flag4 = 0x8000000
};
inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
return static_cast<MyBitMask>( +x & +y );
}
inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
return static_cast<MyBitMask>( +x | +y );
}
Among other things, + converts lambdas to function pointers. Normally the conversion happens automatically, but sometimes it doesn't.
For example, this doesn't compile:
std::array arr{
[](int x){return x*x;},
[](int x){return x*x*x;},
};
You could make it work by specifying the function pointer type as the std::array template parameter, or you could just do this:
std::array arr{
+[](int x){return x*x;},
+[](int x){return x*x*x;},
};
A bit late, but here's a very twisted use that I stumbled across. Apparently the + operator can be useful (if perhaps not strictly necessary) when designing safeguards around the possibility of encountering empty preprocessor tokens. See this post for a more in-depth discussion.
It's practical, but by no means pleasant.
Since for arithmetic variables operator+ generates a new value.
I use it to generate value copies of reference-like (proxy) types.
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
Another option is to use operator* but then the ref_of can be confused with a pointer-like object.
Since for arithmetic variables operator+ generates a new value,
I use it in general to generate value copies of reference-like (proxy) types.
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
...
ref_of<T> r = t;
auto s = +r; // this forces a copy
Another option is to use operator* but then the ref_of can be confused with a pointer-like object.
I could use some help understanding the following in C++, particularly the difference between an operator and a function:
What is an operator?
What is a function?
What is the difference between them?
Is a user-defined operator+() a function or an operator?
Can an operator operate on operands at compile-time? Do they always operate at compile time? (like sizeof() in C++)
An operator is a symbol like +, -, += and so forth (see 13.5). They don't carry a meaning. During semantic analysis, the meaning of an operator is determined.
A function is a constructor, destructor, conversion function (that looks like operator type()) or operator function (function template specialization and instantiation can yield these in turn).
An operator function is something that implements an operator (see 13.5). An example is operator+. These are functions in all respects, and the only difference to "usual" functions is that they may be called implicitly and they have a funny name.
Some operators have a built-in meaning, that can be changed by the programmer. One refers to the built-in meaning of an operator simply by saying built-in operator (see 5/3). However, if such an operator is applied on operands for which a built-in meaning is defined, changing that meaning is only allowed for a few cases (these are assignment, address-of and the comma operator, see 13.5/6).
What is an operator?
An operator is a symbol that is use in expressions.
Examples are: + - * / etc
On built-in types there operations are well defined and unchangable.
For user defined types the operators can be defined as syntactic sugar for a function/method call
Array a;
a = b + c; // a.operator=(b.operator+(c));
What is a function?
We use the term function/method interchangeably most of the time. The only difference is that a method is associated with an instance of a class object. Otherwise they are the same. They provide a way of grouping a set of instructions together.
What is the difference between them?
The action of an operator on a built-in type is defined by the compiler.
The action of an operator on a user defined type is a function call.
Is a user-defined operator+() a function or an operator?
Its a function (or a method). Use of an operator on a user defined type is syntactic sugar for a function call. They are still refereed to as operators though in normal conversation.
Can an operator operate on operands at compile-time?
For built-in types yes. The compiler has extensive ability to optimize there usage.
For user defined types. It can perform optimizations on the operators just like other functions which may lead to there being eliminated, but the code is not executed at compile time.
Do they always operate at compile time? (like sizeof() in C++)
No. sizeof() is relatively unique.
Edit:
To show that operator in user defined class behave just like functions here is an example of using mem_fun_ref
#include <vector>
#include <algorithm>
#include <memory>
#include <functional>
class X
{
public:
// Non standard operators.
// Because std::mem_fun_ref has a known weakness in that it can
// not be used with methods that take parameters be reference.
//
// The principle is the same though. That the operator+ can be
// used anywhere that the add() method can be used.
X& operator+(X* rhs) { return *this;}
X& add(X* rhs) { return *this;}
};
typedef X& (X::*MEMF)(X* rhs);
int main()
{
MEMF p1 = &X::add;
MEMF p2 = &X::operator+;
X value;
std::vector<X> data;
std::for_each(data.begin(),
data.end(),
std::bind2nd(std::mem_fun_ref(&X::operator+),&value));
}
There is no meaningful difference between operators and functions, except that operators have a different syntax. Primitive operators however are not functions.
What is operator?
An operator is generally an operation performed on a variable given some form of punctuation. For example, the default behavior of operator+ between two integers is to add them.
What is function?
A function is a subroutine -- a reuseable block of code.
What is the difference between them?
Nothing, as far as user code is concerned, except for syntax. Note that if you override operator||, operator&&, or (to a lesser extent) operator,, you change the semantics of the built in operator semantics. In the case of && and ||, you make the operation which is normally short circuiting into an operation which is not. In the case of the comma, you would need to ensure that you evaluate the arguments left to right, as the comma operator normally behaves in this way.
Is user-defined operator+() a function or operator?
Neither. It is a user defined operator overload. A function name cannot start with the keyword operator, and an operator is simply the actual punctuation mark used to invoke the operator overload, i.e. + or -. EDIT: Note that while technically speaking it is not a function, it does have the semantics of a function call, as demonstrated in #Martin York's excellent answer.
Can operator operate on operands at compile-time? Do they always operate at compile time? (like sizeof() in C++)
No, sizeof cannot be overloaded. If you want some form of compile time operation done, you need to use something like template metaprogramming. Note that if the compiler is able to do the calculation at compile time it may elide the call into your overloaded operator, of course.
In C++ you can override what the symbols +, -, ==, etc. do when applied to class instances. By defining the "operator+" method in class A, you are telling the compiler what to do with code like:
A a, b, c;
c = a + b; // the + here actually calls a.operator+(b)
It's also a function or more precisely an instance method, in the sense that it's something that gets called.
EDIT: see also http://en.wikipedia.org/wiki/Operator_overloading
and http://en.wikibooks.org/wiki/C++_Programming/Operators/Operator_Overloading
There is no huge difference between functions and operators. You can think of an using operator, e.g., 'a+b', as a shortcut to the function operator+(a,b) which is defined for the types of a and b. Of course, operators on primitive types (like integers) and a few other exceptions are not necessarily defined like this.
Thus, to answer a few of your specific questions:
Is user-defined operator+() a function or operator?
A function that implements an operator.
Can operator operate on operands at compile-time? Do they always operate at compile time?
Since it is a function, it operates at run time, but in some cases compiler optimizations can do work at compile time for certain operators. I'm not 100% sure why you're asking this, so perhaps there is something I'm not aware of here.
There are only two minor differences between functions and operators.
Operators can be used in two ways (x+y or operator+(a,b)).
Operators must have same number of parameters as the built-in one (operator== must have exactly two params). The exception from this rule is function call operator() which can be overloaded with any number of any parameters.
Here are some differences between an operator and a function:
An operator does not push its parameters onto the stack, but a function pushes its parameters onto the stack.
The compiler knows about the operation of the operators, but is not aware of the output of the function. Said a different way, the action of the operator is defined at compilation time and that of a function is defined at the runtime.
Among all things I've learned in C++ (which isn't so much), operator overloading seems the most difficult. In general terms, when is it best to write an operator overload as a friend function? When do I have to explicilty use *this? Is always bad to use a temporary object?
There is nothing magical abourt operator overloading - such overloads are simply functions with strange-looking names. So you write operator overloads in the same way you would write a named function. In fact, it's often a good idea to write a named function first - you can always change it to an operator later.
The only thing that you do have to be aware of is that the compiler makes use of a couple of your operators:
operator=() when storing things in collections
operator<() when sorting/searching things
Neil's answer is correct. In addition, this link provides a lot of good information about when, where, why, and how to use the various types of operator overloading in C++.
In general, I'd try to stick with overloads that are intuitive -- use of the '+' operator should reflect something analogous to addition, etc. If you find yourself doing string comparisons with the '+' operator or something like that, you should probably be using standard functions instead.
The first rule of operators overloading: do not overload operators that make no sense. For instance, the + operator may look like a good choice to append elements to lists, but it is not: not everybody would find this use logical.
Regarding the mathematical operators, friend is unneeded.
The typical way to define them (that respects symmetries and implicit conversions) is the following one:
struct T {
T& operator+=(T const& rhs) {
// the actual addition code
return *this;
}
};
T const operator+(T const& lhs, T const& rhs) {
return T(lhs) += rhs;
};
However, this organization is not adapted to operators like Matrix or
Polynomial multiplication as the *=(T const&) operator is not that trivial. In that
case, we would define operator*=(T const&) on top of operator*(T const&, T const&), and the binary operator*() could be made friend if there is no accessor to the internal data -- this use of friend is not an encapsulation violation, but an encapsulation enforcement --, or for optimization purposes.
If you really want to eliminate most temporaries, have a look at expression templates (see Blitz++, boost.ublas, newmat, ...), or wait for C++0x rvalue references.
All operators overloads as member-function take *this as lvalue,so you need friend in cases you don't want it such overload stream operators as << and >>.In most others cases the use of friends is to break the principle of least privilege.
Other way to overload an operator ,which wasn't said, is to use a global function.