There is no provision in operator C for operator overload; proposals for its addition were rejected on the grounds that many build systems do not have the ability to host multiple functions with the same name. Although C ++ can get around this, for example, by having
void foo(int); int foo(char*); long foo(char *, char **);
compile functions named the same as v__foo_i, i__foo_pc and l__foo_pc_ppc [compilers use different naming conventions, although the C ++ standard prohibits the use of internal double underscores in identifiers to allow compilers to give names of things as above without conflicts]. The authors of the C standard did not want any compilers to modify naming conventions to allow overloading, so they did not provide for it.
It would be possible and useful for the compiler to allow overloading of static and inline functions without creating name problems; this in practice would be just as useful as the ability to overload external links, since you may have a header file:
void foo_zz1(int); int foo_zz2(char*); long foo_zz3(char *, char **); inline void foo(int x) { foo_zz1(x); } inline int foo(char* st) { foo_zz2(st); } long foo(char *p1, char **p2) { foo_zz3(p1,p2); }
I remember watching the built-in compiler for the hybrid between C and C ++, which supported the above as a non-standard extension, but I'm not sure about the details. In any case, even if some C compilers support overloading functions that do not have an external binding, it is not supported by C14, and I do not know (unfortunately) any active efforts to add such a function to future C standards.
However, GCC can be created using macros to support an overload form that is not supported directly in languages ββwith operator overload. GCC includes an internal value that will determine if the expression can be evaluated as a compile-time constant. Using this internal, you can write a macro that can evaluate an expression in various ways (including calling functions) depending on the argument. This can be useful in some cases where the formula will be evaluated as a compile-time constant if the argument of the compile-time constant is given, but will lead to terrible mess if a variable argument is given. As a simple example, suppose you want a 32-bit inverse value. If the value is constant, this can be done using:
#define nyb_swap(x) \ ((((x) & 1)<<3) | (((x) & 2)<<1) | (((x) & 4)>>1) | ((((x) & 8)>>3) ) #define byte_swap(x) \ ( (nyb_swap(x)<<4) | nyb_swap((x) >> 4) ) #define word_swap(x) \ ( (byte_swap(x)<<24) | (byte_swap((x) >> 8)<<16) | \ (byte_swap((x) >> 16)<<8) | (byte_swap((x) >> 24)) )
And an expression like uint32_t x=word_swap(0x12345678); would just load x using 0x87654321. On the other hand, if the value is not constant, the result will be terrible: an expression like uint32_t y=word_swap(x); can generate dozens of instructions; calling a function with a partially expanded outline will be almost as fast, but much more compact. On the other hand, using a loop would prevent the result from being considered a compile-time constant.
Using GCC, you can define a macro that will either use the constant macro specified by the constant, or call the function when the variable is set:
#define wswap(x) \ (__builtin_constant_p((x)) ? word_swap((x)) : word_swap_func((x))
This approach cannot do everything that type-based overloading can do, but it can do many overloads, it cannot.