generic programming is very powerful. c should support it

D

Dave Vandervies

Dave said:
Templates may work fine for functions, but you open the function
overload/name mangling can of worms.

There's no overloading happening here (less<int> and less<double> are
two different functions with two different names; the only difference
from writing less_int and less_double is that the programmer only has
to write the template code once and the compiler handles rewriting it
for every type used), and name mangling can be as simple as replacing
the punctuators with something that the linker will handle gracefully
(say, less$int and less$double, if the linker will treat $ as part of
an identifier).
You would also end up with all of
the messy name resolution rules from C++.

Not having objects or inheritance makes template name resolution rules
a lot simpler; you could probably do it with just these:

If there is a fully specialized template for these parameters, use it.
(Having more than one fully specialized template for the same parameters
would be easily checkable and should probably be a constraint violation)
If there is no fully specialized template, and exactly one partially
specialized one, that matches these parameters
(ex. bogosort<double,pred> or bogosort<T,my_compare_function>), use
that partially specialized one.
If there are more than one partially specialized templates that match
these parameters, the behavior is undefined. (A smart compiler could
detect the condition and complain; a less clever compiler could make
an arbitrary choice about which one to use.)
If there are no fully or partially specialized templates that match the
parameters but there is a fully generic one, use it. (Parameters are
either type names or constant expressions of a specific type, so
there's no ambiguity about whether it matches.)
Attempting to use a template with no matching definition is a constraint
violation.

I don't know the C++ rules, but I'd expect most of the messiness comes
from interactions with overloading and inheritance.

There's nothing in templates that requires objects and inheritance or
overloading, and leaving those out makes specifying the templates a lot
easier (because it reduces the amount of non-obvious interaction rules
that need to be gotten right)


dave
 
I

Ian Collins

Dave said:
There's no overloading happening here (less<int> and less<double> are
two different functions with two different names; the only difference
from writing less_int and less_double is that the programmer only has
to write the template code once and the compiler handles rewriting it
for every type used), and name mangling can be as simple as replacing
the punctuators with something that the linker will handle gracefully
(say, less$int and less$double, if the linker will treat $ as part of
an identifier).
But there is, you have already introduced name mangling required to
resolve overloads of the template less. If you are going to introduce
generics, would you have to introduce some form of name mangling, which
would have to be standardised.

Once you start down the generics road, you'd end up having to support
concrete overloads of less.
Not having objects or inheritance makes template name resolution rules
a lot simpler; you could probably do it with just these:

If there is a fully specialized template for these parameters, use it.
(Having more than one fully specialized template for the same parameters
would be easily checkable and should probably be a constraint violation)
If there is no fully specialized template, and exactly one partially
specialized one, that matches these parameters
(ex. bogosort<double,pred> or bogosort<T,my_compare_function>), use
that partially specialized one.
If there are more than one partially specialized templates that match
these parameters, the behavior is undefined. (A smart compiler could
detect the condition and complain; a less clever compiler could make
an arbitrary choice about which one to use.)
If there are no fully or partially specialized templates that match the
parameters but there is a fully generic one, use it. (Parameters are
either type names or constant expressions of a specific type, so
there's no ambiguity about whether it matches.)
Attempting to use a template with no matching definition is a constraint
violation.
Don't forget normal functions that match.
I don't know the C++ rules, but I'd expect most of the messiness comes
from interactions with overloading and inheritance.
Not in the case of functions templates.
There's nothing in templates that requires objects and inheritance or
overloading, and leaving those out makes specifying the templates a lot
easier (because it reduces the amount of non-obvious interaction rules
that need to be gotten right)
Inheritance is a red herring, we are talking about function templates
here, which would require some form of name disambiguation.

Either way, none of this belongs in C, if you want templates, use C++.
 
D

Dave Vandervies

But there is, you have already introduced name mangling required to
resolve overloads of the template less.

What overloads? Did you actually read what I wrote? less<int> and
If you are going to introduce
generics, would you have to introduce some form of name mangling,

By "some form of name mangling", you of course mean "some way to give
template instantiations consistent and distict names". Which isn't too
difficult; we already have to do that for non-templated functions, and it
already happens differently on different implementations. The difference
is just that instead of translating "less_int" into "less_int" or
"_less_int" or "LESS_I" or "936487bc033df3520d102a0e104cb07f", we're
which
would have to be standardised.

Neither C nor C++ have standardised the conversion between names-as-
they-appear-in-the-source and names-as-they-appear-to-the-linker, and
it hasn't hurt either language, so why would this need to be standardised?

Once you start down the generics road, you'd end up having to support
concrete overloads of less.

Really? How and why?

Not having objects or inheritance makes template name resolution rules
a lot simpler; you could probably do it with just these:
[snip]

Don't forget normal functions that match.

I don't know what language you're talking about, but the C that I'm used
to working with doesn't have normal functions with names that look like
Inheritance is a red herring, we are talking about function templates
here, which would require some form of name disambiguation.

"less<int> is the template `less' with the parameter int, less<double>
is the template `less' with the parameter double" isn't good enough?
What's the ambiguity that you're trying to resolve?

If I'm missing something here, please point it out. If you're just
getting confused because you missed the part where I suggested making
the template parameters part of the function's name instead of using
type inference, then go back and read what I wrote (ALL of it) before
you start arguing with something almost but not entirely unlike what I
actually said.


dave
 
I

Ian Collins

Dave said:
What overloads? Did you actually read what I wrote? less<int> and
less<double> are DIFFERENT FUNCTIONS with DIFFERENT NAMES; what are
we overloading?
Maybe I misunderstood your intent, the reason I implied some form of
overloading was that I assumed the functions would be called thus:

n = less( 1, 2 );

and

n = less( 1.0, 2.0 );

Where (as in C++) the compiler matches the correct template. If this is
the case you can also have a concrete function

int less( int, int )

adding to the resolution rules when the compiler encounters

n = less( 1, 2 );
If you are going to introduce
generics, would you have to introduce some form of name mangling,

By "some form of name mangling", you of course mean "some way to give
template instantiations consistent and distict names". Which isn't too
difficult; we already have to do that for non-templated functions, and it
already happens differently on different implementations. [snip]
I do. It isn't difficult, but can get a little messy when there is more
than one template parameter.
Neither C nor C++ have standardised the conversion between names-as-
they-appear-in-the-source and names-as-they-appear-to-the-linker, and
it hasn't hurt either language, so why would this need to be standardised?
True, but at least for C, the ABI is generally standardised per
platform, where C++ compilers all do their own thing. If C compilers
went the same way as C++, we'd loose one of C's greatest assets - the
ability to link between modules compiled with different compilers on the
same platform.
Really? How and why?
The usage example above.
I don't know what language you're talking about, but the C that I'm used
to working with doesn't have normal functions with names that look like
"less<int>" or "bogosort<double,my_function>".
Are we talking about the declaration, or use of the function. I had
assumed the template type was implied, rather than explicit. This might
be the cause of this confusion.
"less<int> is the template `less' with the parameter int, less<double>
is the template `less' with the parameter double" isn't good enough?
What's the ambiguity that you're trying to resolve?
Again, my assumption of template type being implied by the compiler.
 
D

Dave Vandervies

Maybe I misunderstood your intent, the reason I implied some form of
overloading was that I assumed the functions would be called thus:

n = less( 1, 2 );

and

n = less( 1.0, 2.0 );

Where (as in C++) the compiler matches the correct template.

Ahh. That would account for the confusion; I had intended the templated
function to be called as
n=less<int>(1,2);
and
n=less<double>(1.5,2);
which leaves
n=less(1,2)
available for a concrete function.

If you have overloading already, letting the compiler do type inference
on template calls doesn't cost much and makes the programmer's life
a little bit easier; but the difference is only a matter of syntactic
sugar, and the low-sugar version is easier to specify cleanly.

By "some form of name mangling", you of course mean "some way to give
template instantiations consistent and distict names". Which isn't too
difficult; we already have to do that for non-templated functions, and it
already happens differently on different implementations. [snip]
I do. It isn't difficult, but can get a little messy when there is more
than one template parameter.

Messy, but still fairly straightforward, which is a combination computers
are good at. (Though implementation limits would have to be carefully
thought out. The C++ compiler I use at work likes to warn me that it's
truncating symbols to 255 characters long in the debug information it
saves, and you'd run into the same kinds of problems with name handling
if templates were added to C.)

True, but at least for C, the ABI is generally standardised per
platform, where C++ compilers all do their own thing. If C compilers
went the same way as C++, we'd loose one of C's greatest assets - the
ability to link between modules compiled with different compilers on the
same platform.

That would make a difference, but not to the specification of the
language extension.
(It would require more coordination between different implementations
on a platform than just the "do/don't put a '_' in front" that most
platforms need to make names match up, though, and the C-with-templates
implementors would have to do a better job of it than the C++ implementors
did to make it work.)

Are we talking about the declaration, or use of the function. I had
assumed the template type was implied, rather than explicit. This might
be the cause of this confusion.

That appears to be the case.



Unfortunately I don't know yacc and don't have a C parser readily
available; it seems to me that if I had those it would be possible to
build a C-with-templates precompiler that's ready for people to start
trying to break in a spare afternoon. (Getting something that's actually
hard to break would of course take a while longer.) The back-end would
be easy: convert template calls into calls to the instantiated function,
add all of the instantiations needed, and then spit the parse tree back
out as something you can feed to the C compiler. Learning the tools
and building a front-end would be Rather Harder (and take a lot longer)
than modifying an existing front-end, though.


dave
 
I

Ian Collins

Dave said:
Unfortunately I don't know yacc and don't have a C parser readily
available; it seems to me that if I had those it would be possible to
build a C-with-templates precompiler that's ready for people to start
trying to break in a spare afternoon. (Getting something that's actually
hard to break would of course take a while longer.) The back-end would
be easy: convert template calls into calls to the instantiated function,
add all of the instantiations needed, and then spit the parse tree back
out as something you can feed to the C compiler. Learning the tools
and building a front-end would be Rather Harder (and take a lot longer)
than modifying an existing front-end, though.
Guess what I've just started a little project to investigate :)
 
D

Dave Vandervies

Guess what I've just started a little project to investigate :)

Nifty. I was hoping somebody with the appropriate yacc-fu would be
inspired to do it. I know just enough about how it would be done to
wish I knew how to use the tools to do it.

I would be very interested in hearing how it works (and test-driving
it), and I suspect that the set of other readers of CLC who would as
well is nonempty.


dave
 
S

Serve Laurijssen

Michel Bardiaux said:
And so many people (including me) hate them that gcc
introduced -Wdeclaration-after-statement in gcc4 ...

many people love them too
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top