Templates vs overloaded functions?

D

desktop

If a function should work with different types you normally overload it:

void myfun(int a){
// do int stuff
}

void myfun(std::string str){
// do string stuff
}

void myfun(double d){
// do double stuff
}



But you can also use a specialized template function instead:



template<typename T>
void mytemp(T) {
// "default case" if no other match
}

template<>
void mytemp(int a) {
// in case of int
}

template<>
void mytemp(std::string str) {
// in case of string
}


template<>
void mytemp(double d) {
// in case of double
}


The only difference I have found is the correct template is only used if
the arguments match exactly:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.11

But is that the only difference? Are the types decided at compile time
in both examples etc?
 
V

Victor Bazarov

desktop said:
If a function should work with different types you normally overload
it:
void myfun(int a){
// do int stuff
}

void myfun(std::string str){
// do string stuff
}

void myfun(double d){
// do double stuff
}



But you can also use a specialized template function instead:



template<typename T>
void mytemp(T) {
// "default case" if no other match
}

template<>
void mytemp(int a) {
// in case of int
}

template<>
void mytemp(std::string str) {
// in case of string
}


template<>
void mytemp(double d) {
// in case of double
}


The only difference I have found is the correct template is only used
if the arguments match exactly:

http://www.parashift.com/c++-faq-lite/templates.html#faq-35.11

But is that the only difference? Are the types decided at compile time
in both examples etc?

No. If your code never makes use of 'mytemp(int)' or 'mytemp(double)',
the code for them will never be generated. I heard a rumour that today
linkers can detect that a [regular] function is not used and throw its
code out, but I would have to see it to believe.

Yes, involvement of conversions is the main reason to prefer regular
[overloaded] functions over template specialisations. If you happen
to use mytemp(blah), and 'blah' is 'short', an overloaded function
'mytemp(int)' will be used, whereas 'mytemp<int>(int)' will never be
picked (and the default case will be then used). Same if 'blah' is
'float' -- the 'mytemp<double>' specialisation isn't applicable.

Also, your example contains 3 overloaded functions and 4 functions
based on the template (one generic and three specialised). They are
not exactly equivalent.

V
 
J

James Kanze

desktop wrote:
No. If your code never makes use of 'mytemp(int)' or 'mytemp(double)',
the code for them will never be generated. I heard a rumour that today
linkers can detect that a [regular] function is not used and throw its
code out, but I would have to see it to believe.

Put them in a separate compilation unit, put the results in a
library, and I don't know of a linker which won't incorporate
just the functions it needs. VC++ has an option to support this
even if the functions aren't in separate compilation units, but
I'm not sure whether it is such a good idea.
Yes, involvement of conversions is the main reason to prefer regular
[overloaded] functions over template specialisations. If you happen
to use mytemp(blah), and 'blah' is 'short', an overloaded function
'mytemp(int)' will be used, whereas 'mytemp<int>(int)' will never be
picked (and the default case will be then used). Same if 'blah' is
'float' -- the 'mytemp<double>' specialisation isn't applicable.
Also, your example contains 3 overloaded functions and 4 functions
based on the template (one generic and three specialised). They are
not exactly equivalent.

That's the big difference, of course. If you have a template,
the compiler will do type deduction on it. If it succeeds, the
results will be added to the overload set. If it fails, they
won't be.

In his first example, the results would have been more or less
the same if he had provided overloaded functions, rather than
template specializations. The template function declaration
would be instantiated, but any time it corresponded to an
overloaded non-template function, that function would be chosen
instead.

There is one big difference, however: you can force the function
you want using templates, by explicitly specifying the template
arguments, e.g.:

mytemp< int >( someDouble ) ;

Of course, explicitly casting the argument to the targeted type
has almost the same results: the only difference is if the
conversion uses an explicit constructor, in which case casting
the argument works, but the above would fail.
 

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
473,776
Messages
2,569,603
Members
45,200
Latest member
LaraHunley

Latest Threads

Top