19

I'm trying to understand operators in C++ more carefully.

I know that operators in C++ are basically just functions. What I don't get is, what does the function look like?

Take for example:

int x = 1;
int y = 2;
int z = x + y;

How does the last line translate? Is it:

1. int z = operator+(x,y);

or

2. int z = x.operator+(y);?

When I tried both of them, the compiler errors. Am I calling them wrong or are operators in C++ not allowed to be called directly?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Arvin
  • 1,391
  • 4
  • 19
  • 33
  • 7
    That syntax only works on objects, not fundamental types. – jonsca Aug 29 '11 at 04:10
  • so if i were to create a new class called Class MyInteger with a single int defined as a class member and I make MyIntegers x,y,z and again go z = x + y the operator would then be z = x.operator+(y) right? – Arvin Aug 29 '11 at 04:14
  • 2
    Out of curiosity, are you a python programmer? – Chris Eberle Aug 29 '11 at 04:15
  • Yes, you'd be making a wrapper, basically. – jonsca Aug 29 '11 at 04:19
  • @Chris, no actually I'm a basic-intermediate java programmer – Arvin Aug 29 '11 at 04:20
  • @Arvin - _Technically_ that statement would translate to `z.operator=(x.operator+(y));` but I doubt you'd need to overload `operator=` for a class with a single `int` member. – Chris Lutz Aug 29 '11 at 04:22
  • 3
    @Arvin: N.B.: **C++ IS NOT Java**. Do not program in C++ like you would in Java, or you will feel nothing but frustration. We have [a list of good C++ books](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) that will cover C++ topics you need to know to use C++ effectively. – In silico Aug 29 '11 at 04:31
  • Thanks In silico, I've now realised the two languages are very different. At first I was approaching everything using java knowledge, and things really didn't make much sense. Now I've learnt to throw away everything (so to speak) java so that I can approach C++ as a C++ programmer – Arvin Aug 29 '11 at 16:47

6 Answers6

18

Using C++ standardese, the function call syntax (operator+(x, y) or x.operator+(y)) works only for operator functions:

13.5 Overloaded operators [over.oper]

4. Operator functions are usually not called directly; instead they are invoked to evaluate the operators they implement (13.5.1 - 13.5.7). They can be explicitly called, however, using the operator-function-id as the name of the function in the function call syntax (5.2.2). [Example:

    complex z = a.operator+(b); // complex z = a+b;
    void* p = operator new(sizeof(int)*n);

—end example]

And operator functions require at least one parameter that is a class type or an enumeration type:

13.5 Overloaded operators [over.oper]

6. An operator function shall either be a non-static member function or be a non-member function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.

That implies that an operator function operator+() that only takes ints cannot exist per 13.5/6. And you obviously can't use the function call syntax on an operator function that can't exist.

In silico
  • 51,091
  • 10
  • 150
  • 143
  • Right, so it's the second case in my question. Thanks! – Arvin Aug 29 '11 at 04:18
  • 3
    @Arvin: Wrong! The answer is "it depends". If `operator+` is defined a member function you access it by `x.operator+(y)`. If it is defined as a global function you access it by `operator+(x,y)`. – David Hammen Aug 29 '11 at 04:21
  • @Arvin, nooo, it's both cases in your question. – unkulunkulu Aug 29 '11 at 04:23
  • @David, ah, thanks, so if you implement it in the class, then it's second case, but if you implement it outside then it's the first case? – Arvin Aug 29 '11 at 04:24
  • 2
    @Arvin: you're overthinking it. Member functions are called by using an object of that type. Therefore, if operator+ is a member function, then you call it using member function call syntax. If it is a free function, you call it using free function syntax. Just like with any other function. – Nicol Bolas Aug 29 '11 at 05:20
10

For basic types like int, float, double; the operators are already overloaded/pre-defined, so nothing special can be done for that. And,

int z = x + y;

is the only way to express/call it.

For interpretation purpose, actually both the statements,

int z = operator+(x,y);
int z = x.operator+(y);

are true (had it been overloadable).

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Thanks, but apparently we cannot use operator+(x,y) according to In silico? – Arvin Aug 29 '11 at 04:19
  • 1
    @Arvin, neither `operator+(x,y)` nor `x.operator+(y)` can be used; but for *interpretation purpose*, both are true. Assume that you have a class, then you can overload the operator both the ways. – iammilind Aug 29 '11 at 04:26
6

Operator overloads only apply to objects and structs, not to fundamental types (such as int or float). If you had an object class like:

  class A {
    A operator+(const A& rhs) {
      return someComputedValue;
    }
  }

then you can indeed call myA.operator+(anotherA) and that will be equivalent to myA + anotherA.

fluffy
  • 5,212
  • 2
  • 37
  • 67
  • This is incorrect. If you had overloaded an operator for a POD type then it would also be callable with the operator+() syntax. – Mankarse Aug 29 '11 at 04:15
  • What do you mean exactly Mankarse, so it's not myA.operator+(anotherA) but it's operator+(myA, anotherA) ? – Arvin Aug 29 '11 at 04:17
  • @Mankarse: Redefining what 1+2 means is pure evil. But apparently it is allowed. – David Hammen Aug 29 '11 at 04:28
  • 2
    You can't redefine 1+2, but you can do: `struct POD {int i;POD operator+(POD const& o)const{POD r = {i + o.i};return r;}};`. In which case you could write: `POD podA = {2}; POD podB = {3}; POD podC(podA.operator+(podB));`. – Mankarse Aug 29 '11 at 04:32
  • -1: POD does not imply that there is no operator-overload-member-function, and further, even if, you could still provide operator-overload-free-functions except for some operators. This is answer is **wrong**. – Sebastian Mach Aug 29 '11 at 11:01
  • Sorry, I always thought POD referred to fundamental types, and not to method-less structs. I'll fix my answer accordingly. Thanks for setting me straight. – fluffy Aug 29 '11 at 18:34
3

You can't overload binary operators when both arguments are built in types. However for your own objects this is how you can create them.

//Simple struct that behaves like an int.
struct A
{
  int v_;
  explicit A(int i) : v_(i) {}  
  // A member operator so we can write a+b
  A operator+(const A & a ) const { return A( v_ + a.v_); }      
};

// A non-member operator, so we can write 1+a
A operator+(int i, const A & a)
{
   return A(i+a.v_);
}

int main()
{
  A a(1);
  A b(2);

  // Call the member version using its natural syntax    
  A c = a+b;
  //Call the member version using function call syntax
  A d = a.operator+(b);
  // Call the non-member version using the natural syntax
  A e = 1 + b;
  // Call the nonmember version using function call syntax.
  A f = ::operator+(1,b);
}
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
2

As has been mentioned in commentary and in other answers, by there is no operator+ for fundamental types. For classes, the answer to which of operator+(x,y) versus x.operator+(y) is correct is "it depends". Particularly, it depends on how operator+ was defined. If it was defined as an member function then you need to use x.operator+(y). If it was defined as a global function then you need to use operator+(x,y).

When the compiler confronts the statement z=x+y; your compiler is smart enough to look for the appropriate form. You shouldn't be expecting one or the other. You should be using x+y.

David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • Thanks David, that confirms what I've gathered from the other answers :) – Arvin Aug 29 '11 at 04:26
  • -1: You can't redefine the meaning of "what 1+2 means" because you can't redefine the operations for builtin types. – Sebastian Mach Aug 29 '11 at 11:06
  • @phresnel: That was an edit added after the fact, and it is gone now. It was peripheral to the main point of my post. I added that nonsense (and it is nonsense) after another answer mentioned overloading `operator+` for primitive types. I thought that that was illegal, but I couldn't find anything in the standards that prohibits it. It must be there somewhere because multiple compilers do reject attempts to redefine `operator+` for fundamental types. – David Hammen Aug 29 '11 at 12:15
  • 1
    `5 Expressions [expr], Item 2: Operators can be overloaded, that is, given meaning when applied to expressions of class type (clause 9) or enumeration type (7.2).[...]`, `Item 3: Operator overloading shall not modify the rules for the built-in operators [...]`, `int` e.g. is neither a class or enum type, so you can't. Also, there's already a builtin `operator+` for `int`, so you can't. – Sebastian Mach Aug 29 '11 at 12:18
  • @phresnel: Thanks for the reference. I foolishly looked in section 13.5, Overloaded operators. Who woulda thunk that the correct place to look for what is and isn't allowed with respect to overloading operators is in chapter 5, expressions? – David Hammen Aug 29 '11 at 12:46
  • You are usually better of to just do an incremental search through the whole standard for a quick start :) (-1 removed) – Sebastian Mach Aug 29 '11 at 14:04
1

For native types, the operators aren't functions. Only overloaded operators are functions. Built-in operators are built-in - they don't have "functions", they usually just compile down to one or two assembly instructions that it would be insane to call as a function.

So neither operator+(x, y) nor x.operator+(y) is correct. I suppose x.operator+(y) is less correct because non-struct types can't have members, but I doubt that helps much.

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183
  • Thanks Chris, but what you meant was both of them are incorrect for native types right? For class objects then both can be correct – Arvin Aug 29 '11 at 04:25
  • 1
    @Arvin - Yes. For native types it's incorrect to think of `operator+` but for non-native types it is perfectly fine (and useful). – Chris Lutz Aug 29 '11 at 04:37