Function overloading in C++ by passing arguments by value or by reference (Function Overloading)

Assuming we have this example of functions in C++

void foo(int x)  { std::cout << "foo(int)"   << std::endl; }
void foo(int& x) { std::cout << "foo(int &)" << std::endl; }

Is there a possibility to differentiate which function I want to invoke by making some modification to the call arguments?

If function foo is invoked in any of these modes:

foo( 10);

i = 10;
foo( static_cast<const int>(i));

foo( static_cast<const int&>(i)); // Aunque aquí convertir un tipo básico a través de una referencia no tiene mucha utilidad. Sólo es para exponer los casos posibles.

Invokes the first of the two overloaded functions, because a constant argument cannot be passed by reference to a non-constant parameter. But how would it be done for be able to invoke the second of the overloaded functions? If I perform the following invocation:

int i = 10;
foo( i);

An ambiguity error occurs as both functions are valid for this argument.

In this link https://stackoverflow.com/a/5465379/6717386 exposes that one way to fix it is, in the case of handling objects instead of basic types, to make the copy constructor private so that, being unable to make a copy of the value, it necessarily has than invoking the second function and passing the object by reference. But what about the basic types is there any way? Do you necessarily have to rename the functions to avoid this kind of problems?

 2
Author: Comunidad, 2016-08-15

1 answers

int i = 10;
foo( i);

An ambiguity error occurs as both functions are valid for this argument.

That's right, C++ does not have any mechanism to distinguish between call by copy and call by reference, so answers to and with basic types is there any way? would be a simple no.


But it's a very boring answer, so we'll try using language tools to try to fulfill the target:

void foo(int x)  { std::cout << "foo(int)"   << std::endl; }
void foo(int& x) { std::cout << "foo(int &)" << std::endl; }

We can modify the behavior and skip the ambiguity using the unary operator +:

int i = 10;
foo(+i); // Llamada no ambigua: llama foo(int)

Applying the unary operator + over a type returns its value, so the only option available is to call foo per copy (goodbye ambiguity!)... unfortunately this does not solve the version call for non-constant reference.

The only way to achieve this is to make one of the two options better than the other in case of ambiguity, for example making one of the functions template:

template <typename T>
void foo(T x)  { std::cout   << "foo(int)"   << std::endl; }
void foo(int& x) { std::cout << "foo(int &)" << std::endl; }

int i = 10;
foo(i);  // Llamada no ambigua: foo(int&) es la mejor opcion
foo(10); // Llamada no ambigua: foo(T) es la mejor opcion

When the compiler chooses between a template version and a non-template, the non-template is better option, so the ambiguity is eliminated; unfortunately this last option implies that " must necessarily be renamed to functions to avoid this type of problems", understanding "function name" by the type of the same.

 2
Author: PaperBirdMaster, 2016-08-16 07:41:47