Tony
C99 has overloading only in a very limited sense. The type-generic math
macros act somewhat like functions that were overloaded for float and
long double arguments, with corresponding return types. However, the
rules for those macros are subtly different from those for C++
overloaded functions, and the feature is completely unavailable for
user-written functions.
> My compiler doesn't allow function overloading for C like it does for C++.
> Does the latest standard of C support this or will a future version support
> function overloading?
>
> Tony
The lcc-win32 compiler is a C compiler that supports operator overloading.
See:
http://www.q-software-solutions.com/lcc
The compiler is free of charge and can be downloaded either from there or from
http://www.cs.virginia.edu/~lcc-win32
It runs only under windows (NT/95/98/2000)
--
Jacob Navia Logiciels/Informatique
41 rue Maurice Ravel Tel 01 48.23.51.44
93430 Villetaneuse Fax 01 48.23.95.39
France
Tony
"Jacob Navia" <ja...@jacob.remcomp.fr> wrote in message
news:39D06B2C...@jacob.remcomp.fr...
It was discussed in some detail in this newsgroups several times. But
it's not clear whether it is considered to be useful enough to warrant
the inclusion in a future standard. The best thing you can do is to
provide an implementation which supports some sort of function
overloading, get as much people as you can to use it, and then write a
detailed proposal for the next standardization round.
-- Niklas
Tony
"Niklas Matthies" <matt...@fsinfo.cs.uni-sb.de> wrote in message
news:8qv7j9$14v6d$2...@hades.rz.uni-sb.de...
It seems that function overloading is most useful in conjunction
with user-defined types, e.g. classes, which we considered adding
for C99 but ultimately decided against. Unless something like
C++ classes are added to a future revision of Standard C, it is
unlikely that general function overloading will be made available
to application programs.
Maybe it is better to have the other function though. For how would the
symbol be looked up in a DLL for example if both functions had the same name
(mangling would be necessary?)? It may not be worth the complexity.
Tony
"Douglas A. Gwyn" <gw...@arl.army.mil> wrote in message
news:39D3981A...@arl.army.mil...
From my own developper point of view, overloading leads to confusion,
loss of readability and decrease of karma. Avoid it.
(I actually think the same about syntax hilight, so maybe I am just too
excentric).
Overloading a function is mainly syntaxic sugar: you ask the compiler to
call the right function from the type and number of arguments; however,
this information, you, as a programmer, already have. You can do without
it, with relatively low pain. Besides, overloading raises practical
issues about name mangling in object files.
--Thomas Pornin
Yes, compile-time mangling, or something to the same effect, would be
needed. It is not needed for C as it is today, so there would be some
resistance to imposing this requirement on all implementations.
paul
You don't even have to consider the implementation problems to
decide that you don't want to start from here. Just think about
the horrible situation of exactly which argument types are
acceptable for exactly which parameter types. Confusion over
this caused chaos in the early days of C90, and C99 has added
a LOT more complexity.
It would be extremely hard to add this functionality without
breaking a lot of existing code, though it could probably be
done. But, frankly, C is already so complex that the standard
is seriously ambiguous, and many people don't want to see it
get worse.
Regards,
Nick Maclaren,
University of Cambridge Computing Service,
New Museums Site, Pembroke Street, Cambridge CB2 3QG, England.
Email: nm...@cam.ac.uk
Tel.: +44 1223 334761 Fax: +44 1223 334679
We already have user-defined types. They are called structs, unions,
enums etc.
-- Niklas
> Overloading a function is mainly syntaxic sugar: you ask the compiler to
> call the right function from the type and number of arguments; however,
> this information, you, as a programmer, already have.
A kind of overloading has much sense when a language provides something
similar to what C++ calls templates.
(I'm afraid that C is too low level for this kind of programming.
Without garbage collection it's not fun to operate on polymorphic
lists of unknown elements.)
--
__("< Marcin Kowalczyk * qrc...@knm.org.pl http://qrczak.ids.net.pl/
\__/
^^ SYGNATURA ZASTĘPCZA
QRCZAK
Niklas Matthies wrote:
> It was discussed in some detail in this newsgroups several times. But
> it's not clear whether it is considered to be useful enough to warrant
> the inclusion in a future standard. The best thing you can do is to
> provide an implementation which supports some sort of function
> overloading, get as much people as you can to use it, and then write a
> detailed proposal for the next standardization round.
I proposed "function aliases" a few months ago on news:comp.std.c,
which provide an alternative to overloaded functions without all the
messy linker issues. Essentially, aliases allow the compiler to
substitute unique real function names for non-unique aliased function
names during compilation, so there is no need for name mangling; it
was more of a type-aware name replacement facility.
The idea generated lukewarm enthusiasm.
--
David R. Tribble, mailto:da...@tribble.com, http://david.tribble.com
God willing, no, it will not.
-s
--
Copyright 2000, All rights reserved. Peter Seebach / se...@plethora.net
C/Unix wizard, Pro-commerce radical, Spam fighter. Boycott Spamazon!
Consulting & Computers: http://www.plethora.net/
> Niklas Matthies wrote:
> > it's not clear whether it is considered to be useful enough to warrant
> > the inclusion in a future standard.
>
> It seems that function overloading is most useful in conjunction
> with user-defined types, e.g. classes, which we considered adding
> for C99 but ultimately decided against. Unless something like
> C++ classes are added to a future revision of Standard C, it is
> unlikely that general function overloading will be made available
> to application programs.
I think, it might be useful for not having to invent another name for
basically the same thing all the time. In example: Today I have to
write (this are user defined functions):
string_append(str1,str2); list_append(list1,list2);
Obviously it would be nicer to write:
append(str1,str2); append(list1,list2);
and having the compiler determining the 'right' append function from
the parameter types.
On the other site every such features needs to mess with the function
names (better known as 'name mangling') since one cannot have 2 global
functions with the same name if you use the usual 'ld' mechanism for
linking the object files. While this is no language issue, it means,
that on the system level, when using 'nm','ar' and so on, one will be
confronted with uncomprehensible names. I think transparency is
important, so I'd prefer to fix the namespace concept of traditional
loaders first and then proceed to add overloading or whatever.
Regards -- Markus
In PL/I, I believe this was solved by requiring the programmer to do the
name mangling themselves. To create an overloaded function, you first
defined functions with unique names of your own choosing. Then you mapped
the common name onto each of them. It was something like:
generic foo(fixed int) foo_int;
generic foo(real) foo_real;
Sorry, my memory of this feature is poor, as I never actually used it, but
saw it in a manual once or twice, so I may not have the precise syntax
right. But the basic idea is that the linker only sees the foo_int and
foo_real names.
Something like this could easily be added to C, but it would mean that C's
and C++'s overloading mechanisms would be completely incompatible (although
C++ could also adopt this as an alternative to its normal overload
mechanism).
--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
> I think, it might be useful for not having to invent another name for
> basically the same thing all the time. In example: Today I have to write
> (this are user defined functions):
>
> string_append(str1,str2); list_append(list1,list2);
>
> Obviously it would be nicer to write:
>
> append(str1,str2); append(list1,list2);
>
> and having the compiler determining the 'right' append function from the
> parameter types.
Failure to include function (and to a lesser degree, operator)
overloading in C99 was a great disappointment to me. There are legitimate
if overrated arguments against operator overloading -- it's not clear
that a function is being called with an overloaded operator -- but this
is not as big a complaint with overloaded functions, which merely take
some getting used to.
C does, however, provide a variety of ways to overload functions, most of
which involve using pointers, structs, and/or variadic functions. I'm
working on a Perl-like string library right now, and all of the provided
types are implemented as structs that begin with a type identifier in the
form of an int. When a function takes a void pointer, it can cast the
pointer to a generic struct, examine the type identifier, and then act
appropriately. In this particular case, I've implemented generic
constructors, destructors, copy operators, etc., in the form of a
function table indexed by type identifier.
The one drawback to this method is that you can't mix primitive types
with structs, and it requires a certain degree of care and discipline to
do manually what another language would do for you. Most of this is no
big deal, as you are only compensating for the lack of the syntactic
sugar that C++ provides. Most of the nastiness, which typically involves
moderately confusing multiple dereferences, can be hidden in macros or
utility functions.
Regards,
Eric
> In article <Ubwz5.3033$s76.2...@bgtnsc06-news.ops.worldnet.att.net>,
> Tony <to...@my.isp.net> wrote:
>>My compiler doesn't allow function overloading for C like it does for
>>C++. Does the latest standard of C support this or will a future version
>>support function overloading?
>
> God willing, no, it will not.
Obviously, we are appealing to different gods.
The absence of function overloading is a deficiency. Why? Because it
tends to shift information about argument types from the argument list,
where it belongs, to the name of the function, which is opaque to the
compiler and places an additional burden on the programmer.
-e.
Function overloading is fairly useful in a C++ context, but I think it would
be massively destructive in C. Objects don't have named member functions.
A function that operates on different types of arguments is actually doing
a meaningfully different thing. I would like to keep them distinct.
(One of the reasons is that the presence or absence of a declaration can
then change which of several functions you call, and which conversions are
used to pass data. This is just too surprising.)
One of the things that deeply irritates me is that standard floating
point maths functions in C99 are effectively overloaded, but the
ordinary programmer cannot (AFAIK) provide the same facility for all
those functions that are not in the standard library.
Francis Glassborow Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
>In PL/I, I believe this was solved by requiring the programmer to do the
>name mangling themselves. To create an overloaded function, you first
>defined functions with unique names of your own choosing. Then you mapped
>the common name onto each of them. It was something like:
>
>generic foo(fixed int) foo_int;
>generic foo(real) foo_real;
>
>Sorry, my memory of this feature is poor, as I never actually used it, but
>saw it in a manual once or twice, so I may not have the precise syntax
>right. But the basic idea is that the linker only sees the foo_int and
>foo_real names.
>
>Something like this could easily be added to C, but it would mean that C's
>and C++'s overloading mechanisms would be completely incompatible (although
>C++ could also adopt this as an alternative to its normal overload
>mechanism).
I proposed almost exactly this approach here several years ago. David
Tribble and others proposed (several variants of) a better scheme in
this group here several months ago and worked it out in some detail
(although not enough to reach full agreement...). If your are lucky,
you might be able to find the discussion on Deja.
Personally, I can't see any problem with C and C++ being incompatible
being in this area - I have trouble imagining someone writing a
program large enough to warrant using a feature like this, without
deciding which language they were writing in.
(The problem isn't approaches, it's getting the Committee to deal with
them. Someone has to write a proposal, preferably implement it
somewhere, and figure out if or when the committee accepts such
proposals, if any revisions to the Standard are ever going to be made
again. To date, the Commiittee hasn't felt that this idea warrants the
effort involved - I'm not sure that I disagree.)
--
Peter Curran pcu...@acm.gov (chg gov=>org)
Do you really consider this true in the case of mathematical functions?
While there are a few exceptions (e.g. factorial for integers versus gamma
for floating point), for the most part we think of math as being very
similar for all numeric types.
> A function that operates on different types of arguments is actually doing
> a meaningfully different thing. I would like to keep them distinct.
I disagree that they must be named differently. What about >, +, min,
abs, sin, =, free, []?
How to write code that may operate on different types in the same way?
E.g. a gcd algorithm - why should it be coded separately for all types?
> (One of the reasons is that the presence or absence of a declaration
> can then change which of several functions you call, and which
> conversions are used to pass data. This is just too surprising.)
This is true in C++, but not for overloading in general (it's not
true in Haskell, Clean, Mercury, where overloading is done quite
differently).
Well, in C++ you would have to do this using a template (unless all the
types are derived from a common base class that contains appropriate
virtual members, in which case polymorphism can be used). I sure hope the
people asking for function overloading don't also want to open that can of
worms!
: Function overloading is fairly useful in a C++ context, but I think it would
: be massively destructive in C. Objects don't have named member functions.
: A function that operates on different types of arguments is actually doing
: a meaningfully different thing. I would like to keep them distinct.
: (One of the reasons is that the presence or absence of a declaration can
: then change which of several functions you call, and which conversions are
: used to pass data. This is just too surprising.)
The problem with this arguement is that it is a style issue and not a
capability issue. The presence of function overloading does not
prevent you from keeping distinct function names for different types of
arguments, and conceivably an organization can impose style rules to
enforce this behavior. The reverse is not true, however. The absense
of function overloading does prevent you from using the same name if
you desire.
-- Jonathan Geisler --
>Do you really consider this true in the case of mathematical functions?
Mostly, yes.
>While there are a few exceptions (e.g. factorial for integers versus gamma
>for floating point), for the most part we think of math as being very
>similar for all numeric types.
Yes, with horribly misleading results. :)
There now exists a system where float has a "broader" range than integer, but:
pow(10, 40);
works produces a useful result, and
pow(10.0f, 40.0f)
doesn't.
I find that *deeply* unnerving.
Probably by duplicating the code.
>E.g. a gcd algorithm - why should it be coded separately for all types?
Because "%" doesn't make sense on some of them.
But if you had to write them as pow_int(10, 40) and pow_float(10.04, 40.0f)
it would be OK, even though it doesn't change the fact that the latter
doesn't produce a useful result?
Do you think that if we didn't overload ==, and had to write float_equal(x,
y), that it would prevent people from being screwed by round-off error when
they check for equality? I don't.
Those numeric types where a gcd algorithm makes sense have a good definition
of "%" that makes sense.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
>>I find that *deeply* unnerving.
>But if you had to write them as pow_int(10, 40) and pow_float(10.04, 40.0f)
>it would be OK, even though it doesn't change the fact that the latter
>doesn't produce a useful result?
pow_int(10, 40) isn't the same as pow(10, 40). It's really pow_double(10,
40), because the default is to use doubles. Sneaky, huh.
This is why I am happier with explicit types on many operations.
>Do you think that if we didn't overload ==, and had to write float_equal(x,
>y), that it would prevent people from being screwed by round-off error when
>they check for equality? I don't.
I started to write
It'd catch *some* of them, because they'd read the docs for the
function...
and then realized how funny it is to base an argument on the belief that
documentation is actually read.
I think my issue with overloading is this: I want the overloading to be
knowable in advance. I don't want another developer to be able to *change*
it. It's a little confusing as is (I am occasionally bitten by mistakes
involving the promotion rules and subtle differences between operators in
different contexts), but *I can look it up*.
If someone can add a new function to a shared header, and change the behavior
of code that hasn't been altered, it makes it much harder for me to track
what's going on. I don't like it.
> >E.g. a gcd algorithm - why should it be coded separately for all types?
>
> Because "%" doesn't make sense on some of them.
And *that* is a pity. (Of course I meant types like int, long long
and mpz_t from GMP - not all types).
I understand that this is the way C works, but I disagree that this
is how programming languages should work in general and that all
kinds of overloading are inherently bad. Programming is about finding
abstractions, and many abstractions abstract over types.
bool c_DayOfWeekFromDateType(uint8* day_of_week, DateType* date);
bool c_DayOfWeekFromDate(uint8* day_of_week, uint16 year, uint8 month, uint8
dsy);
bool c_DayOfWeekFromDayNo(uint8* day_of_week, uint32 day_num);
Without overloading I had to create function names with all the
"Fromblahblah" stuff when it's pretty obvious from the args that it isn't
necessary other than to work around the lack of function overloading. So I
just wanted to post another example.
I believe the issue is not whether function overloading would be useful, I
believe everyone here would agree that it is, but rather the issue being how
much complexity it would add to compiler implementations. I wonder if it
could be had without adding any or even simplifying the implementation since
it seems a rather mechanical association construct.
Tony
>Peter Seebach (se...@plethora.net) wrote:
>: In article <8rij9...@enews2.newsguy.com>,
>: Eric O'Dell <eod...@sfmedia.net> wrote:
>: >The absence of function overloading is a deficiency. Why? Because it
>: >tends to shift information about argument types from the argument list,
>: >where it belongs, to the name of the function, which is opaque to the
>: >compiler and places an additional burden on the programmer.
>
>: Function overloading is fairly useful in a C++ context, but I think it would
>: be massively destructive in C. Objects don't have named member functions.
>
>: A function that operates on different types of arguments is actually doing
>: a meaningfully different thing. I would like to keep them distinct.
>
>: (One of the reasons is that the presence or absence of a declaration can
>: then change which of several functions you call, and which conversions are
>: used to pass data. This is just too surprising.)
>
>The problem with this arguement is that it is a style issue and not a
>capability issue. The presence of function overloading does not
>prevent you from keeping distinct function names for different types of
>arguments, and conceivably an organization can impose style rules to
>enforce this behavior. The reverse is not true, however. The absense
>of function overloading does prevent you from using the same name if
>you desire.
I have to agree with this. C isn't the best example here since it's
such a minimalistic language, but in a larger language like C++, there
are some features I just don't use in code I've written myself, like
operator overloading, because I think it's a bad idea.
(An aside: More accurately, I think overloading of primitive operator
symbols is a bad idea. If C++ provided facilities for creating new
operators from a restricted character set, that would be a different
matter. Of course, that's pure syntactic sugar, and probably not very
important.)
Overloaded functions are only confusing if you aren't expecting them.
Otherwise, they form a good tool for conceptually grouping closely
related functions. Personally, I think it would be easier to remember
a single identifier, printf, with very similar argument lists, than to
remember printf, fprintf, sprintf, vfprintf, vprintf, and vsprintf. Of
course it's possible to abuse function overloading, but the same is
true of almost any language feature.
--Eric
+-------------------------------------------------------------------+
| "I have come a very long way from myself only to realize that |
| identity is a skill and self-betrayal is a habit. Once lost, the |
| former is very hard to regain; once gained, the latter is very |
| hard to lose." ---I. Corvus, _The Europe of Our Dreams_ |
+-------------------------------------------------------------------+
Visit sunny Barycenter at: http://barycenter.dyndns.org
So you have carefully written an entire set of functions to replace
operators for primitive types? Well if you haven't you are rather
limited when you write templates for arithmetical types. Overloaded
operators aren't just a piece of syntactic sugar, they are the key to
much generic programming. Of course overloading operators with entirely
different semantics leads to trouble, but so does overloading functions
that way.
--
Jacob Navia Logiciels/Informatique
41 rue Maurice Ravel Tel 01 48.23.51.44
93430 Villetaneuse Fax 01 48.23.95.39
France
Tony
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:8QoaIVAG...@ntlworld.com...
> To see an implementation of operator overloading in C see the
> lcc-wiN32 compiler.
> http://www.q-software-solutions.com/lcc
> This compiler works under windows (NT/95/98/2000)
>
Not function overloading (that's wrong!) but operator overloading!
Sorry about this mistake.
Operator overloads make user-defined types (UDTs) look like fundamental
types; that means that they are most useful when there's some conceptual
similarity between the UDT and one of the fundamental types. The
fundamental types are characters, numbers, pointers, arrays, and
functions, and complicated combinations thereof. For each of those
categories, there's a corresponding category of UDTs where operator
overloading is entirely appropriate: you've already mentioned
mathematical objects. The other categories are smart pointers,
containers, and function objects.
In each of those cases, templates are needed to make the best possible
use of the UDT.
The only exception is characters, probably because C provides few
significant distinctions at the operator level between characters and
integers.
But using a function when a domain expert would naturally use an
operator also makes code less understandable. Which is exactly why the
operators have all been overloaded for the built-in types.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> of code that hasn't been altered, it makes it much harder for me to track
> what's going on. I don't like it.
#define malloc(x) trace_malloc(x)
And there it happens. It's already there.
Regards -- Markus
Undefined behaviour if <stdlib.h> is included.
--
Clive D.W. Feather | Internet Expert | Work: <cl...@demon.net>
Tel: +44 20 8371 1138 | Demon Internet | Home: <cl...@davros.org>
Fax: +44 20 8371 1037 | Thus plc | Web: <http://www.davros.org>
Written on my laptop; please observe the Reply-To address
> In article <xlfy9zy...@neuromancer.informatik.uni-tuebingen.de>,
> Markus Leypold <ley...@informatik.uni-tuebingen.de> writes
> >#define malloc(x) trace_malloc(x)
>
> Undefined behaviour if <stdlib.h> is included.
Umpf. Yes. Take some other example in a similar spirit. Tcsh does it.
What I wanted to say: Keeping people from changing the meaning of
names is perhaps not an argument against function overloading in an
environmement where a preprocessor is present. It's just discussing
about, wether not the 10th hole in the wall might sink your ship.
Regards -- Markus
>And there it happens. It's already there.
1. That's not officially correct.
2. With overloaded functions, people are *likely* to add new versions of
an existing function, because that's what the feature is for.
consider:
double generic sqrt(double);
int generic sqrt(int);
This would instruct the compiler to generate two entries in the public
export for this object file:
_sqrt_double
and
_sqrt_int
When the compiler sees:
int data;
...
data = sqrt(data);
it could replace the call to that generic function with
data = _sqrt_int(data);
Since there isn't any object oriented approach here, we can easily resolve
ambiguities with a set of rules.
Normal arithmetic promotions are done if there is no immediate match. If
still we have no match, this is an error.
There are special cases, as always:
int generic foo(int, char);
int generic foo(char, int);
foo(4,9);
Which one should the compiler call?
I think this is an error, and that the programmer should be forced to write:
foo_int_char(4,9);
The mangling algorithm is transparent, and the names are written in clear
text. Actually is the almost the same as we do now by hand, only that when
we wanted it, it can be done automatically, without typing too much. This
gives the language an easier interface.
Problem is how to mark generic functions. A special keyword is too ugly to
be considered. How could we specify this?
We have to, if we want to avoid generalizing name mangling to all functions
and loosing all language interchange possibilities that make one of the
strengths of C.
"Eric O'Dell" <eod...@sfmedia.net> wrote in message
news:8rij9...@enews2.newsguy.com...
> In article <39da7ab1$0$28243$3c09...@news.plethora.net>, "Peter Seebach"
> <se...@plethora.net> wrote:
>
> > In article <Ubwz5.3033$s76.2...@bgtnsc06-news.ops.worldnet.att.net>,
> > Tony <to...@my.isp.net> wrote:
> >>My compiler doesn't allow function overloading for C like it does for
> >>C++. Does the latest standard of C support this or will a future version
> >>support function overloading?
> >
> > God willing, no, it will not.
>
> Obviously, we are appealing to different gods.
>
> The absence of function overloading is a deficiency. Why? Because it
> tends to shift information about argument types from the argument list,
> where it belongs, to the name of the function, which is opaque to the
> compiler and places an additional burden on the programmer.
>
>
> -e.
By your above rule, none, because there is no immediate match, and
the arguments already are promoted.
> Problem is how to mark generic functions. A special keyword is too
> ugly to be considered. How could we specify this?
extern "C2010" {
int foo(int, char);
int foo(char, int);
};
:)
-- Niklas
I proposed "function aliases" for C about two months ago in
news:comp.std.c, which accomplishes the same thing as you want.
I used a different syntax, making use of the obsolete 'entry' keyword:
extern float sinf(float x);
extern double sind(double x);
// Declare aliases for sin()
entry sin
{
float sin(float x) = sinf(x);
double sin(double x) = sind(x);
}
void foo()
{
double x;
x = sin(1.0f); // = sinf(1.0f)
x = sin(1.0); // = sind(1.0)
}
In effect, the name 'sin()' is replaced at compile time by the
matching alias 'sinf()' or 'sind()'. It is an error if no matches
are found.
The advantage of my syntax is that it could be expanded to allow
calls to alias functions to be replaced with arbitrary expressions,
e.g.:
extern int wbar(float x, int flag);
entry bar
{
int bar(float x) = wbar(x, 1) + 100;
int bar(long x) = wbar((float)x, 2) - 100;
int bar(int x) = bar((long) x);
}
In other words, function aliases act more like a type-aware function
macro preprocessor, capable of replacing arbitrary function calls
(matching defined prototypes) with inline calls to other functions
(or possibly with arbitrary inline expressions).
The only problem is defining rules for resolving function aliases
when combined with the usual type widening rules.
--
David R. Tribble, mailto:da...@tribble.com, http://david.tribble.com
This is quite long... compare with:
double overloaded sin(float x), sin(double x);
That's all. Quite shorter.
You can declare:
int sqrt(int);
double overloaded sqrt(double);
But you cannot declare
int sqrt(int);
double sqrt(double);
The keyword is required in the first or the second entry. This would avoid
that we loose the errors when by accident we declare wrongly a function!
> In effect, the name 'sin()' is replaced at compile time by the
> matching alias 'sinf()' or 'sind()'. It is an error if no matches
> are found.
Yes, but you have to create those names!
That's precisely what we want to avoid. Having the programmer figuring up
those names.
I agree with you that's an error if no matches are found, but if more than
one match is found that's an error too.
The rules should be:
Try match with no promotions first. If no matches are found,
Promote each argument. If still no match error. If more than one match
error.
>
> The only problem is defining rules for resolving function aliases
> when combined with the usual type widening rules.
Well, I don't know. Will implement it first, to really see all the
implications.
That's what *you* want to avoid. Other people want to avoid making
the linker choose the names, so that C can retain its simple linkage
model.
paul
Are you proposing a standard name mangling algorithm? If not, you'll end
up with C++'s problem where object files compiled by one implementation
can't be linked with object files compiled by a different implementation.
In the case of C++ this isn't too bad, since there are so many details that
can vary between implementations (others include how vtables are
implemented, how "this" is passed, and how static initialization is done).
But C has always had a relatively straightforward mapping, and
cross-linking is rarely a problem.
> In article <8t7dts$km7$1...@wanadoo.fr>,
> jacob navia <ja...@jacob.remcomp.fr> wrote:
> >> In effect, the name 'sin()' is replaced at compile time by the
> >> matching alias 'sinf()' or 'sind()'. It is an error if no matches
> >> are found.
> >
> >Yes, but you have to create those names!
> >
> >That's precisely what we want to avoid. Having the programmer figuring up
> >those names.
> >I agree with you that's an error if no matches are found, but if more than
> >one match is found that's an error too.
>
> Are you proposing a standard name mangling algorithm? If not, you'll end
> up with C++'s problem where object files compiled by one implementation
> can't be linked with object files compiled by a different implementation.
> In the case of C++ this isn't too bad, since there are so many details that
> can vary between implementations (others include how vtables are
> implemented, how "this" is passed, and how static initialization is done).
In C++'s case, I wouldn't say "not too bad", I'd say "ideal". The alternative to
discovering incompatibility at link time is mysterious failure at run time.
Wait, the linkage model remains! That's why we need that "overloaded" or
whatever keyword.
I repeat:
1: All names remain the same
2: Functions with the "overloded" keyword will be decorated with the name of
their arguments. That's all.
double overloaded sin(double);
int overloaded sqrt(int);
means that there will be two functions exported:
sqrt_double
sqrt_int
The advantage is that the compiler figures out those names for us. NO other
changes to the language are necessary, and the linkage model remains the
same!
The mangled names should not interfere with valid user-defined symbol
names though, but instead should be in the namespace reserved for the
implementation, .e.g. __ovrld__sqrt_double.
One problem might still be that these names get too long. For example,
mangled names involving structure types will need to include the types
and names of all members, recursively. Same goes for all other derived
types. So if you have a function taking pointers to some complicated
structure types containing some enums and some pointers to other
complicated structure types, you'll easily get mangled names with
lengths of a few hundred, thousand or even more of characters.
Another major issue here would be how to mangle self-referencial
structure types, i.e. containing pointers to themselves, incomplete
types and empty function parameter lists.
-- Niklas
If I want to force call on sqrt(int) I can always write:
sqrt_int(2.3);
Prepending an underscore would force the programmer to write:
_sqrt_int(2.3);
Your proposal however avoids the problem with:
int *sqrt_int(struct foo * p); // defines a function that happens to clash
with overloaded mangling
double overloaded sqrt(double);
int sqrt(int);
> One problem might still be that these names get too long. For example,
> mangled names involving structure types will need to include the types
> and names of all members, recursively.
No!
double overloaded foo(struct bar *p);
would be
_foo_struct_bar_p
The rules are:
o underscore (maybe)
o function name
o underscore
o typename of first arg
o underscore
o typename second arg
o underscore
etc
Pointer signs ("*") are replaced by "p", i.e. int * is int_p
Yes, but by enabling this, you are certain to get lots of clashes with
existing code and libraries.
> > One problem might still be that these names get too long. For example,
> > mangled names involving structure types will need to include the types
> > and names of all members, recursively.
>
> No!
> double overloaded foo(struct bar *p);
>
> would be
> _foo_struct_bar_p
This is not good. If different (sets of) translation units use different
structure types with the same tag independently, they should be able to
be linked together.
-- Niklas
You'd better write : sqrt((int)2.3);
and leave the name mangling in peace. The thing is more transparent that
way.
--Thomas Pornin
In C we can always write:
int foo(int);
int (*pFn)(int);
and then
pfn = foo;
What happens when "foo" is overloaded? Which function should be called?
I think this is not possible but maybe one of you finds a solution. By the
way, how does C++ solve the problem?
One possible way would be to find a function among the set of functions
called "foo" that matches the prototype exactly, i.e. in the example, find
an overloaded version of foo that exactly has an integer argument.
And now you have the compiler creating names that may conflict with user
provided names. There is no way of providing name mangling unless you do
something such as C++'s reservation of all double underscores to
implementors. I much prefer the proposal that we be able to,
effectively, provide an overloaded alias for a set of function names
that I, as the coder, choose. That, seems to me, to be a simple way to
provide a general facility that would not easily be abused.
I'll quote from the C++ standard (snipping stuff only related to
template functions, member functions, and other non-C features):
13.4 Address of overloaded function
A use of an overloaded function name without arguments is resolved in
certain contexts to a function [or] a pointer to function [···]
for a specific function from the overload set. The function selected
is the one whose type matches the target type required in the
context. The target can be
- an object [···] being initialized,
- the left side of an assignment,
- a parameter of a function [which are always prototyped in C++],
[···]
- the return value of a function [···], or
- an explicit type conversion
The overloaded function name can be preceded by the & operator. An
overloaded function name shall not be used without arguments in
contexts other than those listed. (/Note:/ any redundant set of
parentheses surrounding the overloaded function name is ignored
(5.1).)
> One possible way would be to find a function among the set of functions
> called "foo" that matches the prototype exactly, i.e. in the example, find
> an overloaded version of foo that exactly has an integer argument.
Right.
In a previous posting, a cast on the arguments was suggested for a
function call to select a specific function from an overload set:
sqrt((int) 4.2) /* calls int sqrt(int) */
Maybe a better way would be
((int (*)(int)) sqrt)(4.2)
because this doesn't obscure argument type mismatches, and makes it
possible to "#define sqrt_int ((int (*)(int)) sqrt)". On the other hand,
this could be fatal if sqrt is not an overloaded function name at all.
Probably the safest thing to do would be to provide a builtin operator to
select a specific function from an overload set:
#define sqrt_int __overload_select__(sqrt, int)
-- Niklas
> This is not good. If different (sets of) translation units use different
> structure types with the same tag independently, they should be able to
> be linked together.
If they use the same name for non-overloaded function, they should be
able to be linked together too. Yet C does not allow it. Why should
it handle a weirder kind of name clash? Fix the basic problem first.
--
__("< Marcin Kowalczyk * qrc...@knm.org.pl http://qrczak.ids.net.pl/
\__/
^^ SYGNATURA ZASTĘPCZA
QRCZAK
> There is no way of providing name mangling unless you do something
> such as C++'s reservation of all double underscores to implementors.
This is not true, even without extending the charset used for encoded
names. Mangled names can be put in the reserved namespace and use
underscores (or any other character) to escape what mangling needs
and escape underscores themselves.
Because the very purpose of overloading function names is to remove the
limitation that a function name alone already uniquely determines a
(non-static) function. With overloaded function names, the name *and*
the type of the function needs to be known to determine the designated
function. Hence it seems straightforward to me that functions with an
overloaded function name should have the same external linkage symbols
if and only if their types are compatible, if an automatic name mangling
scheme is going to be imposed.
> Fix the basic problem first.
Of course it would be nice to get the same behavior for regular
functions (i.e. functions with a non-overloaded function name), and it
would already be legal to so today, e.g. by encoding the function types
into the object files and letting the linker check if they match.
Unfortunately you can't do this without breaking the established linkage
conventions (i.e. that only the function name determines the external
symbol), so it's currently not practicable to impose this as a
requirement (i.e. requiring a diagnostic).
However, letting the programmer chose the linkage names herself, as has
alternatively been proposed, very probably is the best way extend C to
provide function name overloading.
-- Niklas
int overloaded foo(long long)
double overloaded foo(double);
and you want (for wahtever reasons) to force a choice you can:
(double (*)(double))foo(7);
i.e. *cast* the overloaded name. This good idea was previously mentioned
here, and I think it's better than my original proposal.
The only problem is that the syntax is quite unappealing... :-(
How could we solve that?
Writing the name in clear text as I wanted to do
foo_double(7);
is problematic because that ties the code too much to a specific mangling
schema. Of course if we could stanrdadize the schema so that all C compilers
interoperate that would be OK, but that's kind of difficult.
Consider the following case:
double overload my_sqrt(double x);
double overload my_sqrt_double();
You could cope with this by prohibiting the use of function names that
would conflict with the name mangling scheme. However, reserving double
underscore so it can be used to distinguish mangled names from
user-defined ones is a much simpler approach.
And also incorrect. You've cast the value returned by foo(). To cast foo
itself requires an additional pair of parentheses:
((double (*)(double))foo)(7);
> double overload my_sqrt(double x);
> double overload my_sqrt_double();
>
> You could cope with this by prohibiting the use of function names that
> would conflict with the name mangling scheme. However, reserving double
> underscore so it can be used to distinguish mangled names from
> user-defined ones is a much simpler approach.
There is no need to prohibit such names. They could be mangled e.g. thus:
__overload_my_usqrt
__overload_my_usqrt_adouble
with _u meaning "escaped underscore" and _a meaning "the type of an
argument follows".
OK. Now what are the advantages of this scheme over a scheme that uses a
reserved double underscore? You're now using two characters to separate
off the argument list, and another pair for each source code underscore
in the mangled name. That means that you've lost all space advantage
over the double underscore scheme (that advantage was already
unnecessarily squandered by your "__overload_" prefix). It's also harder
to read. I don't see any compensating advantage.
The advantage, as opposed to generally reserving double underscores, is
that the space of names reserved for implementations need not to be
expanded. We can do with the existing reserved names.
-- Niklas
Apart from parantheses missing in the above example, this method is also
not perfect, as I already stated in another post, because the cast might
hide errors. Consider:
void goo(void);
int overloaded foo(long long);
double overloaded foo(double);
((double (*)(double))goo)(7); /* oops, wrote goo instead of foo
-- no diagnostic required */
> The only problem is that the syntax is quite unappealing... :-(
>
> How could we solve that?
#define foo_double ((double (*)(double))foo)
But I'd suggest a dedicated operator/macro:
__mangle_overloaded(foo, double)
should expand to the mangled name of foo(double).
However, please consider the other proposed scheme where the programmer
and not the compiler gets to choose the mangled name.
-- Niklas
Exactly, and that is the way C++ does it.
No. Whatever you do fails because UDTs can be named with combinations of
embedded underscores and letters, you simply cannot produce a name
mangling algorithm without support by reserving some character or
combination of characters.
All names starting with double underscores or underscore and an
upper-case letter are already reserved. Where's the problem?
-- Niklas
In how you generate the rest of the identifier.
One may or may not use double underscores for the rest of the identifier
(see the proposal with the escape syntax). My understanding was that the
issue under discussion was whether double underscores should be
generally reserved for the implementation, which, in C, they are not,
currently, and I see no need to change that.
-- Niklas
You still have not dealt with the problem. Mangling requires some
mechanism for elaborating the function name to provide information about
the parameter (and possibly return type). I know of no method of doing
this without the provision of some reserved character or character
string that delimits the elaboration of the different parameters.
One commonly used method is: Pick some character that will be used to
introduce escape sequences with special meaning. To denote the character
itself, use a suitable escape sequence, for example the character (to
introduce the escape sequence) followed by itself. C string and
character literal syntax uses this; '\' is the escape character, and
'\\' denotes a literal '\'.
You can do the same or a similar thing with underscores for name
mangling. For example, '__' not followed by another double underscore
shall be the token seperator, and '____' (two double underscores) shall
be a literal double underscore. The following mangling would result:
Function Mangled name
sqrt(int) __ovr_sqrt__int
foo_bar(size_t, struct my__type) __ovr_foo_bar__size_t__struct__my____type
Other encodings that need less space (but may be harder to read) are
also possible. This is really straightforward stuff.
-- Niklas
For what we're talking about here, isn't there an even easier answer? How
about using a character that isn't legal as part of a C identifier at all?
I suspect that on most systems, the linker deals with arbitrary strings,
which are represented in object files in a structured fashion, not as
identifiers that have to be parsed. So the encoding of a mangled name
could begin with a non-alphanumeric character like "=" or "#", or use that
character instead of underscore to separate the function name from the
argument types, e.g. sqrt#int and sqrt#float.
The only problem I imagine with this is for compilers that don't generate
object files directly, but instead generate assembler code. If the
assembler has restrictions on the characters that can be used in a label,
and doesn't provide a way to escape special characters, they might prevent
a compiler from generating these mangled names.
--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
This would change the requirements the C standard imposes with regard to
external linkage identifiers. This should be avoided, since it will make
overloading much less likely to be included in the standard. Using
additional characters would also make it impossible to call the actual
function from C code compiled without overload support.
-- Niklas
What is quite interesting is the application of this feature to
constructors.
Suppose:
typedef struct _Person {
char *Name;
int Age;
} Person;
Person * overloaded newPerson(void)
{
return (Person *)malloc(sizeof(Person));
}
Person * overloaded newPerson(char *name)
{
Person *result = malloc(sizeof(Person));
result->name = name;
return result;
}
Person * overloaded newPerson(char *name,int age)
{
Person *result = malloc(sizeof(Person));
result->name = name;
result->Age = age;
return result;
}
Now in my code I can write:
Person *p = newPerson();
Person *p1 = newPerson("John Smith");
Person *p2 = newPerson("John Smith",25);
There is no need to create different identifiers: newPerson,
newPersonFromString, newPersonFromStringAndInt, etc!
I think the language gains with this feature.
Note too that in my implementation you CAN STILL write:
int overloaded;
and it will work as it always has.
You can write:
int overloaded(int foo)
{
...
}
and it will still work as it always has. There is NO NEW KEYWORD, and that's
why I think this extension to lcc-win32 is compatible with the ANSI
standard, that doesn't forbid extensions.
I will give a test to the implementation over the week-end and post an
experimental version on Monday.
I thank to all people that contributed to this thread.
typedef int *overloaded;
overloaded foo(int);
This perfectly legal code would not compile with the "overloaded" keyword
schema. I took some time to find the solution:
Implicit "int" is not allowed for overloaded functions. That feature is
obsolecent anyway, so this restriction cleanly solves it.
With this problem solved, now I am pretty confident that there is no logical
contradiction in this schema. The proposed syntax would be:
1) Short form:
result type "overloaded" identifier '(' args list ')'
Example:
double overloaded sqrt(double);
int overloaded sqrt(int);
Here the compiler will supply a name automatically for the given arguments
list. This is the default behaviour.
2) long form
result type "overloaded identifier '.' identifier '(' args list ')'
The long form allows the programmer to specify the mangled name for the
function. This is the name that the compiler will emit as exports in the
interface of the generated object file.
Example:
double overloaded sqrt.DblSqrt(double);
int overloaded sqrt.IntSqrt(int);
This means that the function sqrt will have two meanings depending on the
arguments list: either a call to a function named DblSqrt when given a
double, or a call to IntSqrt when it is given an integer. This solves the
problem of incompatibilities and allow programs compiled with this extension
to easily interface other software.
I would be thankful to anyone that finds a logical contradiction to this
schema.
OK, but such things further extend the length of the name (and note that
C, unlike C++, still has a limit on the maximum length identifier that
systems are required to support)
Sorry, I am now between Toronto and home so this comment will be several
days late.
Right. I'm not saying that I'm in favor of such a standardized name
mangling scheme for C (I'm not). I was just saying that there is no
necessity to add all names containing double underscores to the set of
names reserved for the implementation.
-- Niklas
>> That's what *you* want to avoid. Other people want to avoid making
>> the linker choose the names, so that C can retain its simple linkage
>> model.
jacob navia wrote:
> Wait, the linkage model remains! That's why we need that "overloaded"
> or whatever keyword.
>
> I repeat:
> 1: All names remain the same
> 2: Functions with the "overloded" keyword will be decorated with the
> name of their arguments. That's all.
>
> double overloaded sin(double);
> int overloaded sqrt(int);
>
> means that there will be two functions exported:
>
> sqrt_double
> sqrt_int
>
> The advantage is that the compiler figures out those names for us.
> NO other changes to the language are necessary, and the linkage model
> remains the same!
All you've invented is a name mangling algorithm. What happens with
this code?:
double overloaded sin(double x);
float overloaded sin(float x);
int sin_double(); // name collision?
Your name mangling is far from transparent to the programmer.
However, it is possible to invent a name mangling algorithm that does
not intrude upon the programmer's namespace, e.g.,
int weeble__float(const struct FooBarInfo *p)
becomes
__13weeble__floatPCS10FooBarInfo()
The problem is that this scheme can easily generate names longer than
the minimum required by the standard (31 significant initial
characters in external identifiers; UCNs take up more than one
character, see 5.2.4.1). (The mangled name above is 32 characters
long.)
And such a scheme might very well be incompatible with existing C++
compilers.
Niklas Matthies wrote:
> However, please consider the other proposed scheme where the
> programmer and not the compiler gets to choose the mangled name.
(Thank you.) My function alias scheme entirely avoids the problem of
having the compiler choose mangled names by leaving it up to the
programmer to choose the underlying (unmangled) function names.
To recap my proposed syntax:
extern float sinf(float x);
extern double sind(double x);
entry sin
{
float sin(float x) = sinf(x);
double sin(double x) = sind(x);
}
--
David R. Tribble, mailto:da...@tribble.com, http://david.tribble.com
I proposed to Jacob Navia (via email) a simplified version of the above
scheme:
entry sin { sinf, sind };
(I used 'overload' instead of 'entry', but that doesn't matter much.)
The identifiers between the braces must have function type, must have been
previously declared, and no two of them may have compatible argument
lists.
Obviously, this simplified scheme doesn't allow for parameter
conversion (these could still be done by wrapper (inline) functions).
Its advantage is that it is really very simple. :)
Another advantage is that parameter lists don't need to be duplicated,
and no parameter names need to be introduced (which otherwise are prone
to conflict with macro names).
Oh, and I can't get this example of possible abuse out of my head:
#include <stdio.h>
entry print { printf, fprintf, sprintf, snprintf, vprintf, vfprintf,
vsprintf, vsnprintf, fputs, fputc, putchar };
:)
-- Niklas
Will certainly do so because they do not agree with each other.
>
>Niklas Matthies wrote:
>> However, please consider the other proposed scheme where the
>> programmer and not the compiler gets to choose the mangled name.
>
>(Thank you.) My function alias scheme entirely avoids the problem of
>having the compiler choose mangled names by leaving it up to the
>programmer to choose the underlying (unmangled) function names.
>
>To recap my proposed syntax:
>
> extern float sinf(float x);
> extern double sind(double x);
>
> entry sin
> {
> float sin(float x) = sinf(x);
> double sin(double x) = sind(x);
> }
And this is the form that I would like us to seriously consider. It
seems to me to be non-invasive in so far as you do not pay for it if you
do not use it. The only problem is how to deal with inexact matches, and
my preference here would be to require (in C) that only exact matches be
used, all others should require explicit calls to the implementing
function.
BTW, overload entry lists could be used to resolve common uses that
included type conversions/promotions.
Whatever the syntax, it would be nice if the overloading of a name did
not have to be declared all at once, so that (for example) foo.h could
have
extern void foo_print(struct foo *);
entry print { void print(struct foo *p) = foo_print(p); }
and bar.h could have
extern void bar_print(struct bar *);
entry print { void print(struct bar *p) = bar_print(p); }
--
John Rickard <John.R...@virata.com>
> In article <39FF5BA9...@tribble.com>, David R Tribble
> >
> >To recap my proposed syntax:
> >
> > extern float sinf(float x);
> > extern double sind(double x);
> >
> > entry sin
> > {
> > float sin(float x) = sinf(x);
> > double sin(double x) = sind(x);
> > }
>
> And this is the form that I would like us to seriously consider. It
> seems to me to be non-invasive in so far as you do not pay for it if you
> do not use it. The only problem is how to deal with inexact matches, and
> my preference here would be to require (in C) that only exact matches be
> used, all others should require explicit calls to the implementing
> function.
Things to discuss:
1. The syntactic sugar around it ("entry sin" in the example). Quite
arbitrary, except there should be SOME keyword, and some curly braces, and
inside these braces one can only overload one single name, so you cannot
mix float sin (float x), double sin (double x), float cos (float x),
double cos (double x) IMHO.
2. I like the syntax <function_declaration_without_body> = <expression>.
Should the right side be restricted to a function call, or should it be
any arbitrary expression? I would tend to suggest any arbitrary
expression, but nothing more complicated.
3. Resolution rules: I suggest this: Types and number of arguments are
determined. All candidates that could be called if they were normal
functions are determined, for example sin (1) would be legal if sin were a
normal function with either a float or double argument. If there are zero
or one candidates things are obvious. For example, if you have sin (float
x) and sin (void* x) then sin ("hello world") calls sin (void* x).
If there is more than one candidate then I think there should be no
complicated rules, just require that there must be an exact match on all
arguments. In the example, sin (0.0) and sin (0.0f) are legal, sin (0) is
not. In each case there are two candidates but one exact match.
You could want more complicated rules, but I think we should either do
with these very simple rules, or go the whole way like C++. Anything in
between is no good. And the simple way is better IMHO.
4. Evaluation: The arguments and the expression are evaluated in any
order, except any argument is evaluated before it is used obviously. No
sequence points IMHO. Or should there be a sequence point before and after
the expression is evaluated? If so, is the expression evaluated in one
piece or could several expressions be evaluated at the same time?
5. No recursion. It is allowed to call other overloaded functions in the
<expression>, even with the same name, but it is not legal if the same
function is selected again. The compiler must catch this.
6. Is something like entry sin { float sin (float x) = sinf (x); double
sin (float x) = sind (x); } legal? It is of course not possible to
successfully call sin, but does the compiler have to catch this at the
time of the "entry" declaration or only at the time of a call?
From distant memory, I remember that C++ originally had an "overload"
keyword, working very similar to what you proposed, and they removed it
because there were problems exactly with this. If C++ tried it and
rejected it later, then maybe it is not a good idea.
If you allow arbitrary expressions, then what you're really doing is just
an anonymous inline function, so why not make it explicit. That way you
could also have the full capabilities (i.e., a body with statements) that
inline functions have. You also no longer need the separate section for
overloading.
E.g., (s/entry/more_suitable_keyword/ if you like)
#include "mystuff.h"
extern float sinf(float x);
extern double sind(double x);
entry float sin(float x) { return sinf(x); }
entry double sin(double x) { return sind(x); }
entry mytype sin(mytype x) {
// <insert arbitrary function body here>
return <whatever>;
}
Maybe you can additionally allow
entry sin = sinf, sind;
as a shorthand syntax for the simple case.
The compiler already has most of the internal mechanism necessary since
it has to implement "inline". You can even overload the "inline" keyword
for this purpose, instead of "entry". You then don't need any new syntax
at all (excluding the shorthand suggestion), just a change in the
semantics of "inline" to handle the case of multiply defined functions
with the same name. Any function name multiply defined is implicitly
overloaded, and that name can't be used as a function pointer value.
Else (to my first "if" way above), if you're not going to allow
expressions, then all you need is a list of the mapped function names.
E.g.,
extern float sinf(float x);
extern double sind(double x);
entry sin { sinf, sind }
or maybe
entry sin = sinf, sind;
I.e., The types of sinf and sind already tell you all you need to know.
--
David Tanguay d...@Thinkage.ca http://www.thinkage.ca/~dat/
Thinkage, Ltd. Kitchener, Ontario, Canada [43.24N 80.29W]
I thought about it. First I thought you were wrong, but I think your
proposal is ok. The problem that I saw was this: We want to avoid name
mangling like in C++, because that is what creates the real problem.
Therefore I assumed that we cannot really create overloaded functions
(like three functions named sin with some name mangling in the object
file), so allowing inline functions that might be too complicated for the
compiler to inline would create a problem. Basically I assumed that
inlining must be guaranteed.
However, there is no problem. As you propose it, the effect is that only
inline functions can be overloaded. And that saves us: Either the compiler
does really inline the function call. Or it has to create a function body,
but that would be the function body of a static function, so the compiler
can choose an arbitrary name. It only needs to make sure that there are no
conflicts with the names of other static functions or maybe static
variables, which is a much simpler problem.
So the syntax could be
inline sin {
float sin (float x) { ... return ... }
double sin (double x) { ... return ... }
...
}
That is the keyword "inline", followed by an identifier, followed by a
"{", followed by one or more functions with the same name as the
identifier, followed by a "}".
The address of "sin" cannot be taken. (sin) in brackets means an original,
not overloaded function - that might be important if your original library
supplies float sinf (float x), double sin (double x) and long double sinl
(long double x) - there must be a way for the overloaded double sin
(double x) to call the original one! So I might write
inline sin {
float sin (float x) { return sinf (x); }
double sin (double x) { return (sin) (x); }
long double sin (long double x) { return sinl (x); }
// I want this to call the double function but return a float
// Just an example to make things complicated.
float sin (int x) { return (float) (sin) (x); }
// or float sin (int x) { return (float) sin ((double) x); }
}
Semantics would be: sin (arguments) picks the right inline function to
call or complains, then it calls the inline function with the semantics of
a normal function call. Some rules are needed for static variables used,
to decide whether two compilations must / may / may not share the same
implementation of an inline function.
My understanding is that it was dropped because it proved redundant to
the way C++ provides overloading.
How, again, do C++ implementations do overloading? And would a C
implementation do it differently?(Just briefly please).
Tony
>"Christian Bau" <christ...@isltd.insignia.com> wrote in message
>news:christian.bau-0...@christian-mac.isltd.insignia.com...
>> In article <IDg*0z...@news.cam.virata.com>, John.R...@virata.com wrote:
>
>> From distant memory, I remember that C++ originally had an "overload"
>> keyword, working very similar to what you proposed, and they removed it
>> because there were problems exactly with this. If C++ tried it and
>> rejected it later, then maybe it is not a good idea.
>
>How, again, do C++ implementations do overloading?
They use automatic name mangling. Typically the argument types (but
not the return type) are encoded into the mangled symbol name that
is used for each function.
>And would a C implementation do it differently?(Just briefly please).
Yes. C++ implementations generally need extra linker support anyway,
to handle global constructors/destructors and template instantiation.
Given that you've got all that extra mechanism anyway, it's reasonable
to use some kind of name mangling -- at very least you'll need it for
template instantiations, even if you don't use it for overloaded
functions, and so you might as well use it for overloaded functions too.
Furthermore, at the time the "overload" keyword was dropped from C++,
C++ didn't have the same installed base of existing object code that C
does. For C implementations, changing the name mangling is
unfortunately not possible anytime in the near or even medium term
future, since it would break binary backwards compatibility.
--
Fergus Henderson <f...@cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
In practice or in theory. In practice every function name is elaborated
with coded information about its parameter type, and return type. The
problem is for the compiler to
1) create an overload set (remember that C++ has many scopes in which
functions can be declared) which is non-trivial
2) then if there is no exact match for a call it has to exercise quite a
complicated set of rules involving conversions and promotions to see if
there is a best match.
> And would a C
>implementation do it differently?(Just briefly please).
Well the simplest scheme would be to require only an exact match. Indeed
the 'inline' scheme has a lot going for it. It allows type dependant
choice while avoiding most of the complexities that C++ requires.
I recall that the 'overload' keyword was removed from C++ because it
just plain wasn't necessary.
John Rickard wrote:
> Whatever the syntax, it would be nice if the overloading of a name did
> not have to be declared all at once, so that (for example) foo.h could
> have
>
> extern void foo_print(struct foo *);
> entry print { void print(struct foo *p) = foo_print(p); }
>
> and bar.h could have
>
> extern void bar_print(struct bar *);
> entry print { void print(struct bar *p) = bar_print(p); }
I agree. It would be nice for multiple headers to add to the list
of aliases for any given function, provided that none of the aliases
has the exact same prototype. (This is analogous to adding to the
contents of namespaces in C++.)
Tony
"Fergus Henderson" <f...@cs.mu.oz.au> wrote in message
news:8tsgvh$sh7$1...@mulga.cs.mu.OZ.AU...
This makes it easy for separate headers to add to an existing
overloaded name, and avoids duplication (and thus inconsistency) of
information.
Declaration: the "initialization" expression is a (list of) function
designator or another overloaded name, which gets added to the
resolution list. It is a constraint violation to declare an
identifier as _Overload if it has already been declared as anything
but an overloaded name in the same scope, and vice versa. It is a
constraint violation to add two functions with the same number and
respective types of arguments to the resolution list for the same
overloaded name. It is a constraint violation to declare an
identifier as _Overload if it has previously been declared as
_Overload const.
Name resolution: check the function designators first, if any, then
recurse breadth-first on the sub-overloaded names, if any. At each
level of recursion, if there's exactly one potential match by the
usual type conversions, use it. Otherwise, if there's exactly one
exact match, use it. Otherwise it is a constraint violation. (There
is no match, or no unambiguous match, or multiple sub-overloaded names
match exactly.)
This suggests easy application to OO programming in overloaded C:
foo.h:
typedef struct foo foo;
foo* foo_copy_str(char*);
foo* foo_copy_foo(foo*);
_Overload const foo_copy={ foo_copy_str, foo_copy_foo };
_Overload copy=foo_copy;
Should '_Overload foo={};' (or '_Overload foo;') be allowed? (I don't
see why not, but I also don't see any use for it.) Should there be a
way to replace (instead of append to) the resolution list for an
overloaded name? (I say no.)
What about this:
int foo_i(int);
_Overload foo=foo_i;
_Overload bar=foo;
double foo_d(double);
_Overload foo=foo_d;
Should bar now be able to resolve to foo_d? What if bar had been
declared const instead? Should it be a constraint violation for a
const overloaded name to include (recursively) non-const overloaded
names?
I'm not in favor of using "entry" (low mnemonic value) or anonymous
inline functions (breaks orthogonality).
paul