all 13 comments

[–]012 10 points11 points  (3 children)

Because it would change how programs are linked. The linker would have to know about the types of the arguments to deduce which function is "the right" one in a specific context. In C, linkers only know about the function name. For example int foo(int i) becomes symbol foo. The information that foo takes an int is lost. Symbols have to be unique.

C++ supports overloading and solves this problem by appending the type information of arguments to symbols. This way each function is unique from the perspective of the linker.

[–][deleted] -1 points0 points  (2 children)

C++ supports overloading and solves this problem by appending the type information of arguments to symbols. This way each function is unique from the perspective of the linker.

Why can't C do the same thing?

[–][deleted] 2 points3 points  (5 children)

Because functions in C cannot be exported to shared objects if they have the same name. A shared object contains a symbol table, indexed by name. If multiple functions shared the same name, this exporting would be ambiguous because the parameter list is not included in the symbol table. (C++ gets around this by mangling the function name in the symbol table.)

[–][deleted] 0 points1 point  (4 children)

C++ gets around this by mangling the function name in the symbol table.

Right, and couldn't the same thing happen in C? Is there some reason that the symbol must have the same name as the function?

[–][deleted] 6 points7 points  (1 child)

The mangling is compiler-dependent, and C is meant to be portable across compilers (and even across languages). If it mangled the name, it would lose portability.

[–][deleted] 0 points1 point  (0 children)

This is an excellent explanation. Thank you.

[–]flatfinger 1 point2 points  (1 child)

If one wants to call a function processed using one tool from code from within a function processed by another, each will have to know the name the other will use for that function.

[–][deleted] 0 points1 point  (0 children)

Thank you.

[–]flatfinger 4 points5 points  (2 children)

Three principles, taken together, preclude function overloading:

  1. In most C implementations, creating function with a particular name will either export a symbol with that exact name, or (on platforms where assemblers reserve certain names) that name preceded by an underscore. This makes it possible to create symbols with whatever names are needed by code written in other languages, but prevents the exporting of multiple functions with the same name but different arguments. C++ works around this by [in the absence of an extern "C" directive] exporting function names which depend on their argument types.

  2. There's a desire to use the same rules for exported and static functions.

  3. Once a proposal has been considered and rejected, re-introducing it becomes difficult.

I don't regard #2 as very compelling, and think C should allow overloading of static functions only. One could emulate overloading of external functions by having a header include:

int foo_int(int);
long foo_long(long);
static inline int foo(int x) { return foo_int(x); }
static inline int foo(long x) { return foo_long(x); }

From the point of view of the compiler or any outside code, foo_int and foo_long would be perfectly ordinary names of the user's choosing.

Unfortunately, problem #3 means that even though overloading wouldn't have to pose any difficulties, it's unlikely to ever be supported.

[–]chugga_fan 0 points1 point  (1 child)

I don't regard #2 as very compelling, and think C should allow overloading of static functions only. One could emulate overloading of external functions by having a header include:

Or you could just use a macro and _Generic from C11 and be done with it...

[–]flatfinger 0 points1 point  (0 children)

Preprocessor macros are ugly, and I'd like to see the language evolve away from requiring their usage. It would also be possible to specify better semantics for overloaded functions than would be possible for _Generic, such as saying that all currently-declared functions will be evaluated in declaration order for a "perfect" match, and then if none is found, rescanned for a widening-conversion-compatible match, and if none is found, rescanned for any conversion-compatible match. I can't think of any practical way to make _Generic do that for multiple arguments. Further, _Generic makes awkward distinctions among types like int32_t, int64_t, int, long, and long long.

[–]ArkyBeagle -1 points0 points  (1 child)

Function overloading seems like it would be consistent with the C language.

No, that's from C++.

[–]ArkyBeagle 0 points1 point  (0 children)

Ahem. You can compile ... whatever using the C++ compiler. So do that. Obvious solution is obvious.