Sobrecarga de funciones Basada en Valor vs. Referencia Const


Declara algo como lo siguiente

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

¿Alguna vez tuvo sentido? ¿Cómo podría la persona que llama ser capaz de diferenciar entre ellos? He intentado

foo(9);  // Compiler complains ambiguous call.

int x = 9;
foo(x);  // Also ambiguous.

const int &y = x;
foo(y);  // Also ambiguous.
Author: kirakun, 2011-03-29

5 answers

La intención parece ser diferenciar entre invocaciones con temporarios (es decir, 9) y el paso de argumentos 'regular'. El primer caso puede permitir que la implementación de la función emplee optimizaciones, ya que está claro que los argumentos se eliminarán después (lo cual es absolutamente sin sentido para literales enteros, pero puede tener sentido para objetos definidos por el usuario).

Sin embargo, el estándar actual del lenguaje C++ no ofrece una manera de sobrecargar específicamente para el 'valor-l/r' de los argumentos-cualquier valor-l que se pase como argumento a una función puede convertirse implícitamente en una referencia, por lo que la ambigüedad es inevitable.

C++11 introduce una nueva herramienta para un propósito similar-usando referencias de valor r , puede sobrecargar de la siguiente manera

void foo(int x)        { ... }
void foo(const int &&x) { ... }

... y foo(4) (un valor r temporal pasado como argumento) causaría que el compilador escogiera la segunda sobrecarga mientras que int i = 2; foo(i) escogería la primera.

(nota: incluso con el nuevo toolchain, no es posible diferenciar entre los casos 2 y 3 en su muestra!)

 9
Author: Alexander Gessler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-28 03:06:37

Puedes hacer esto con una plantilla:

template<typename T> void foo(T x) { ... }

Entonces puedes llamar a esta plantilla por valor o por referencia:

int x = 123;
foo<int>(x);  // by value
foo<int const&>(x);  // by refernce
 3
Author: Inverse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-29 02:42:41

¿Cómo podría la persona que llama ser capaz de diferenciar entre ellos?

No se puede diferenciar en este caso. Ambas funciones sobrecargadas tienen el mismo tipo de tipo de datos primitivo que el argumento. Y tomar por referencia no cuenta para un tipo diferente.

 2
Author: Mahesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-28 21:34:41

El compilador no puede. Ambas definiciones de foo se pueden usar para todas las 'variantes' de int.

En el primer foo, se hace una copia del int. Copiar un int siempre es posible.

En el segundo foo, se pasa una referencia a un const int. Dado que cualquier int puede ser lanzado a un const int, también se puede pasar una referencia a él.

Dado que ambas variantes son válidas en todos los casos, el compilador no puede elegir.

Las cosas se vuelven diferentes si, por ejemplo, usa lo siguiente definición:

void foo (int &x);

Ahora llamándolo con foo(9) tomará la primera alternativa, ya que no puede pasar 9 como una referencia int no constante.

Otro ejemplo, si reemplaza int por una clase donde el constructor de copia es privado, entonces el llamador no puede hacer una copia del valor, y la primera variante foo no será utilizada.

 1
Author: Patrick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-15 15:06:45

No en C++. Los lenguajes funcionales como Erlang y Haskell se acercan más al permitirle especificar sobrecargas de funciones basadas en el valor del parámetro, pero la mayoría de los lenguajes imperativos, incluido C++, requieren una sobrecarga basada en la firma del método; es decir, el número y el tipo de cada parámetro y el tipo del valor devuelto.

La palabra clave const en la firma no define el tipo del parámetro, sino su mutabilidad dentro de la función; un parámetro "const " generará un error del compilador si es modificado por la función o pasado por referencia a cualquier función que no utilice también const.

 0
Author: KeithS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-28 21:33:54