¿Hay alguna forma de lograr la sobrecarga de funciones en C? Estoy buscando funciones simples para sobrecargar como
foo (int a)
foo (char b)
foo (float c , int d)
Creo que no hay un camino directo; Estoy buscando soluciones si existen.
c
overloading
FL4SOF
fuente
fuente
Respuestas:
Hay pocas posibilidades:
fuente
¡Si!
En el tiempo transcurrido desde que se hizo esta pregunta, el estándar C (sin extensiones) ha ganado efectivamente el soporte para la sobrecarga de funciones (no operadores), gracias a la adición de la
_Generic
palabra clave en C11. (compatible con GCC desde la versión 4.9)(La sobrecarga no está realmente "incorporada" de la manera que se muestra en la pregunta, pero es muy fácil implementar algo que funcione así).
_Generic
es un operador en tiempo de compilación en la misma familia quesizeof
y_Alignof
. Se describe en la sección estándar 6.5.1.1. Acepta dos parámetros principales: una expresión (que no se evaluará en tiempo de ejecución) y una lista de asociación de tipo / expresión que se parece un poco a unswitch
bloque._Generic
obtiene el tipo general de la expresión y luego "cambia" para seleccionar la expresión del resultado final en la lista para su tipo:La expresión anterior se evalúa como
2
: el tipo de expresión controladora esint
, por lo que elige la expresión asociada conint
el valor. Nada de esto queda en tiempo de ejecución. (Ladefault
cláusula es opcional: si la deja desactivada y el tipo no coincide, provocará un error de compilación).La forma en que esto es útil para la sobrecarga de funciones es que puede ser insertado por el preprocesador de C y elegir una expresión de resultado basada en el tipo de argumentos pasados a la macro de control. Entonces (ejemplo del estándar C):
Esta macro implementa una
cbrt
operación sobrecargada , enviando el tipo de argumento a la macro, eligiendo una función de implementación apropiada y luego pasando el argumento de macro original a esa función.Entonces, para implementar su ejemplo original, podríamos hacer esto:
En este caso podríamos haber usado una
default:
asociación para el tercer caso, pero eso no demuestra cómo extender el principio a múltiples argumentos. El resultado final es que puede usarfoo(...)
en su código sin preocuparse (mucho [1]) sobre el tipo de sus argumentos.Para situaciones más complicadas, por ejemplo, funciones que sobrecargan un mayor número de argumentos o números variables, puede usar macros de utilidad para generar automáticamente estructuras de despacho estáticas:
( implementación aquí ) Entonces, con un poco de esfuerzo, puede reducir la cantidad de repeticiones para que se parezca a un lenguaje con soporte nativo para sobrecarga.
Por otro lado, ya era posible sobrecargar el número de argumentos (no el tipo) en C99.
[1] tenga en cuenta que la forma en que C evalúa los tipos podría tropezarlo. Esto elegirá
foo_int
si intenta pasarle un literal de caracteres, por ejemplo, y necesita meterse un poco si desea que sus sobrecargas admitan literales de cadena. Sin embargo, en general sigue siendo bastante bueno.fuente
Como ya se dijo, la sobrecarga en el sentido de que quiere decir no es compatible con C. Un idioma común para resolver el problema es hacer que la función acepte una unión etiquetada . Esto se implementa mediante un
struct
parámetro, donde elstruct
mismo consiste en algún tipo de indicador de tipo, como anenum
, y aunion
de los diferentes tipos de valores. Ejemplo:fuente
whatever
s en funciones separadas (set_int
,set_float
, etc.). Luego, "etiquetar con el tipo" se convierte en "agregar el nombre del tipo al nombre de la función". La versión en esta respuesta implica más tipeo, más costo de tiempo de ejecución, más posibilidades de errores que no se detectarán en el momento de la compilación ... ¡No veo ninguna ventaja para hacer las cosas de esta manera! ¿16 votos a favor?Este es el ejemplo más claro y conciso que he encontrado demostrando la sobrecarga de funciones en C:
https://gist.github.com/barosl/e0af4a92b2b8cabd05a7
fuente
Si su compilador es gcc y no le importa hacer actualizaciones manuales cada vez que agrega una nueva sobrecarga, puede hacer un poco de macro magia y obtener el resultado que desea en términos de llamadas, no es tan bueno escribir ... pero es posible
mira __builtin_types_compatible_p, luego úsalo para definir una macro que haga algo como
pero sí desagradable, simplemente no
EDITAR: C1X obtendrá soporte para expresiones genéricas de tipo que se ven así:
fuente
Sí, más o menos.
Aquí tienes un ejemplo:
Producirá 0 y hola ... desde printA e printB.
fuente
El siguiente enfoque es similar al de a2800276 , pero con algo de magia macro C99 añadida:
fuente
Puede que esto no ayude en absoluto, pero si está usando el sonido metálico puede usar el atributo sobrecargable: esto funciona incluso cuando se compila como C
http://clang.llvm.org/docs/AttributeReference.html#overloadable
Encabezamiento
Implementación
fuente
En el sentido que quieres decir, no, no puedes.
Puedes declarar una
va_arg
función comovoid my_func(char* format, ...);
, pero deberá pasar algún tipo de información sobre el número de variables y sus tipos en el primer argumento, como lo
printf()
hace.fuente
Normalmente, una verruga para indicar que el tipo se agrega o se antepone al nombre. Puede salirse con la suya con algunas macros, pero depende de lo que intente hacer. No hay polimorfismo en C, solo coerción.
Se pueden realizar operaciones genéricas simples con macros:
Si su compilador admite typeof , se pueden poner operaciones más complicadas en la macro. Luego puede tener el símbolo foo (x) para admitir la misma operación en diferentes tipos, pero no puede variar el comportamiento entre diferentes sobrecargas. Si desea funciones reales en lugar de macros, es posible que pueda pegar el tipo en el nombre y usar un segundo pegado para acceder a él (no lo he probado).
fuente
La respuesta de Leushenko es realmente genial, únicamente: el
foo
ejemplo no se compila con GCC, que falla alfoo(7)
tropezar con laFIRST
macro y la llamada a la función real ((_1, __VA_ARGS__)
, quedando con una coma excedente. Además, estamos en problemas si queremos proporcionar sobrecargas adicionales , tales comofoo(double)
.Así que decidí elaborar la respuesta un poco más, incluso para permitir una sobrecarga vacía (
foo(void)
que causó algunos problemas ...).La idea ahora es: ¡Defina más de un genérico en diferentes macros y deje seleccionar el correcto según el número de argumentos!
El número de argumentos es bastante fácil, basado en esta respuesta :
Eso es bueno, resolvemos uno
SELECT_1
o másSELECT_2
(o más argumentos, si los quiere / necesita), por lo que simplemente necesitamos definiciones apropiadas:OK, ya agregué la sobrecarga vacía; sin embargo, esta no está cubierta por el estándar C, que no permite argumentos variados vacíos, es decir, ¡entonces confiamos en las extensiones del compilador !
Al principio, una llamada de macro vacía (
foo()
) todavía produce un token, pero uno vacío. Por lo tanto, la macro de conteo en realidad devuelve 1 en lugar de 0 incluso en una llamada de macro vacía. Podemos "fácilmente" eliminar este problema, si colocamos la coma después de manera__VA_ARGS__
condicional , dependiendo de que la lista esté vacía o no:Eso parecía fácil, pero la
COMMA
macro es bastante pesada; Afortunadamente, el tema ya está cubierto en un blog de Jens Gustedt (gracias, Jens). El truco básico es que las macros de funciones no se expanden si no se siguen entre paréntesis, para más explicaciones, eche un vistazo al blog de Jens ... Solo tenemos que modificar las macros un poco a nuestras necesidades (voy a usar nombres más cortos y menos argumentos para la brevedad).Y ahora estamos bien ...
El código completo en un bloque:
fuente
¿No puedes usar C ++ y no usar todas las demás funciones de C ++ excepto esta?
Si todavía no hay una C estricta, recomendaría funciones variadas .
fuente
Intente declarar estas funciones como
extern "C++"
si su compilador lo admitiera, http://msdn.microsoft.com/en-us/library/s6y4zxec(VS.80).aspxfuente
Espero que el siguiente código lo ayude a comprender la sobrecarga de funciones
fuente