Is there any way to achieve function overloading in C? I am looking at simple functions to be overloaded like
foo (int a)
foo (char b)
foo (float c , int d)
I think there is no straight forward way, looking for workarounds if any?
Is there any way to achieve function overloading in C? I am looking at simple functions to be overloaded like
foo (int a)
foo (char b)
foo (float c , int d)
I think there is no straight forward way, looking for workarounds if any?
There are few possibilities:
Can't you just use C++ and not use all other C++ features except this one?
If still no just strict C then I would recommend variadic functions instead.
In the sense you mean — no, you cannot.
You can declare a va_arg
function like
void my_func(char* format, ...);
, but you'll need to pass some kind of information about number of variables and their types in the first argument — like printf()
does.
Normally a wart to indicate the type is appended or prepended to the name. You can get away with macros is some instances, but it rather depends what you're trying to do. There's no polymorphism in C, only coercion.
Simple generic operations can be done with macros:
#define max(x,y) ((x)>(y)?(x):(y))
If your compiler supports typeof, more complicated operations can be put in the macro. You can then have the symbol foo(x) to support the same operation different types, but you can't vary the behaviour between different overloads. If you want actual functions rather than macros, you might be able to paste the type to the name and use a second pasting to access it (I haven't tried).
As already stated, overloading in the sense that you mean isn't supported by C. A common idiom to solve the problem is making the function accept a struct
parameter. The struct
itself would consist of some sort of type indicator and a union of the different types of values. Example:
#include <stdio.h>
#define T_INT 1
#define T_FLOAT 2
#define T_CHAR 3
typedef struct {
int type;
union {
int a;
float b;
char c;
} my_union;
} my_struct;
void set_overload (my_struct *whatever)
{
switch (whatever->type)
{
case T_INT:
whatever->my_union.a = 1;
break;
case T_FLOAT:
whatever->my_union.b = 2.0;
break;
case T_CHAR:
whatever->my_union.c = '3';
}
}
void printf_overload (my_struct *whatever) {
switch (whatever->type)
{
case T_INT:
printf("%d\n", whatever->my_union.a);
break;
case T_FLOAT:
printf("%f\n", whatever->my_union.b);
break;
case T_CHAR:
printf("%c\n", whatever->my_union.c);
break;
}
}
int main (int argc, char* argv[])
{
my_struct s;
s.type=T_INT;
set_overload(&s);
printf_overload(&s);
s.type=T_FLOAT;
set_overload(&s);
printf_overload(&s);
s.type=T_CHAR;
set_overload(&s);
printf_overload(&s);
}
The following approach is similar to a2800276's, but with some C99 macro magic added:
// we need `size_t`
#include <stddef.h>
// argument types to accept
enum sum_arg_types { SUM_LONG, SUM_ULONG, SUM_DOUBLE };
// a structure to hold an argument
struct sum_arg
{
enum sum_arg_types type;
union
{
long as_long;
unsigned long as_ulong;
double as_double;
} value;
};
// determine an array's size
#define count(ARRAY) ((sizeof (ARRAY))/(sizeof *(ARRAY)))
// this is how our function will be called
#define sum(...) _sum(count(sum_args(__VA_ARGS__)), sum_args(__VA_ARGS__))
// create an array of `struct sum_arg`
#define sum_args(...) ((struct sum_arg []){ __VA_ARGS__ })
// create initializers for the arguments
#define sum_long(VALUE) { SUM_LONG, { .as_long = (VALUE) } }
#define sum_ulong(VALUE) { SUM_ULONG, { .as_ulong = (VALUE) } }
#define sum_double(VALUE) { SUM_DOUBLE, { .as_double = (VALUE) } }
// our polymorphic function
long double _sum(size_t count, struct sum_arg * args)
{
long double value = 0;
for(size_t i = 0; i < count; ++i)
{
switch(args[i].type)
{
case SUM_LONG:
value += args[i].value.as_long;
break;
case SUM_ULONG:
value += args[i].value.as_ulong;
break;
case SUM_DOUBLE:
value += args[i].value.as_double;
break;
}
}
return value;
}
// let's see if it works
#include <stdio.h>
int main()
{
unsigned long foo = -1;
long double value = sum(sum_long(42), sum_ulong(foo), sum_double(1e10));
printf("%Le\n", value);
return 0;
}
Try to declare these functions as extern "C++"
if your compiler supports this, http://msdn.microsoft.com/en-us/library/s6y4zxec(VS.80).aspx
If your compiler is gcc and you don't mind doing hand updates every time you add a new overload you can do some macro magic and get the result you want in terms of callers, it's not as nice to write... but it's possible
look at __builtin_types_compatible_p, then use it to define a macro that does something like
#define foo(a) \
((__builtin_types_compatible_p(int, a)?foo(a):(__builtin_types_compatible_p(float, a)?foo(a):)
but yea nasty, just don't