4

Suppose I define some function f with the following 3 signatures in C++:

void f(int x) {}
void f(int& x) {}
void f(const int& x) {}

These functions can coexist since they differ in the types of the arguments.

Now I run the following code:

int main {
   int i = 3;
   const int ci = 4;

   f(3);
   f(i);
   f(ci);
}

How does C++ know which overloaded function to call in this specific case ? What are rules in general ( best practice ? ) for writing overloaded functions in C++ as to avoid ambiguity. Does the current C++14 standard specify any specific rules ?

Mutating Algorithm
  • 2,604
  • 2
  • 29
  • 66
  • "What are rules in general for writing overloaded functions in C++ as to avoid ambiguity" The best rule is to not overload unless it intuitively makes perfect sense to a human reader. – Sergey Kalinichenko Jan 15 '16 at 00:12
  • I doubt you have actually tested compiling code that has those declarations. At least both clang++ and g++ give an error because of ambiguous call. – J.J. Hakala Jan 15 '16 at 00:15

3 Answers3

7

You cannot overload:

void f(int x) {}
void f(const int& x) {}

Given those, the compiler won't be able to disambiguate the following call:

f(10);

You cannot overload:

void f(int x) {}
void f(int& x) {}

Given those, the compiler won't be able to disambiguate the following call:

int i = 0;
f(i);

You can overload:

void f(int& x) {}
void f(int const& x) {}

Given those, you can use:

int i = 0;
f(i);    // Resolves to f(int&)
f(10);   // Resolves to f(int const&)
R Sahu
  • 204,454
  • 14
  • 159
  • 270
7

All three calls are ambiguous, so the program won't compile.

f(3);

This could use either the first or third overload. They are equally good, so the call is ambiguous.

f(i);

This could use the first, second, or third overload. The second is better than the third; binding to int& is preferred over binding to const int& when it's possible. So it's fine to overload on cv-qualification in this way. But there is an ambiguity between the first and second overloads.

f(ci);

This could use the first or third overload. Again, they are equally good, so the call is ambiguous.


The standard precisely specifies the rules of overload resolution. They are very complicated, so it is a bad idea to overload functions in a way that makes it hard for the reader to tell which overload will be called. You can find the rules here.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312
0

void f(int x) {} The function will have a copy of the object, it will be temporary so don't use it if you want to modify the value or pass a large amount of data.

void f(int& x) {} Same but passed by reference so it's kind of a pointer from the c but you can use it like a usual object. You will be able to modify it and it's better to pass large amount of data because the compiler doesn't have too copy it.

void f(const int& x) {} const before the argument mean that the object can't be modified. And by the way you don't have to declare it as const in your main.

I'm not sure for the function calling case part so I won't answer that ;)

Remi Hirtz
  • 134
  • 3
  • 16
  • It was assumed in the question that these could coexist. They do not since the compiler cannot distinguish them as the parameter type is basically `int x` in all of the three cases. – J.J. Hakala Jan 15 '16 at 00:24
  • @J.J.Hakala They certainly can coexist. They can even be called individually by manually selecting the overload by converting to a function pointer. – Brian Bi Jan 15 '16 at 00:48
  • @Brian I didn't think of function pointers, it is certainly possible to get a function pointer to each of the functions. I guess I should have phrased my comment differently, something like "Those three function definitions cannot coexist if one is expected to call f() directly as in the question." – J.J. Hakala Jan 15 '16 at 01:15