Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
156 views
in Technique[技术] by (71.8m points)

c++ - function template overloading

Can anybody summarize the idea of function template overloading? What matters, template parameter or function parameter? What about the return value?

For example, given a function template

template<typename X, typename Y> void func(X x, Y y) {}

what's the overloaded function template?

1) template<typename X> void func(X x, int y) {}
2) template<typename X, typename Y> X func(X x, Y y) {}
3) template<class X, class Y, class Z> void func(X x, Y y, Z z) {}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Of that list only the second introduces ambiguity, because functions - regardless of whether they are templates - can't be overloaded based on return type.

You can use the other two:

template<typename X> void func(X x, int y);

will be used if the second argument of the call is an int, e.g func("string", 10);

template<class X, class Y, class Z> void func(X x, Y y, Z z);

will be used if you call func with three arguments.


I don't understand why some other answers mentions that template functions and function overloading doesn't mix. They certainly do, and there are special rules how the function to call is selected.

14.5.5

A function template can be overloaded with other function templates and with normal (non-template) functions. A normal function is not related to a function template (i.e., it is never considered to be a specialization), even if it has the same name and type as a potentially generated function template specialization.)

A non-templated (or "less templated") overload is preferred to templates, e.g

template <class T> void foo(T);
void foo(int);

foo(10); //calls void foo(int)
foo(10u); //calls void foo(T) with T = unsigned

Your first overload with one non-template parameter also falls under this rule.

Given choice between several templates, more specialized matches are preferred:

template <class T> void foo(T);
template <class T> void foo(T*);

int i;
int* p;
int arr[10];

foo(i);  //calls first
foo(p);   //calls second
foo(arr); //calls second: array decays to pointer

You can find a more formal description of all the rules in the same chapter of the standard (Function templates)


And finally there are some situations where two or more overloads would be ambiguous:

template <class T> void foo(T, int);
template <class T> void foo(int, T);

foo(1, 2);

Here the call is ambiguous, because both candidates are equally specialized.

You can disambiguate such situations with the use of (for example) boost::disable_if. For example, we can specify that when T = int, then the second overload shouldn't be included as an overload candidate:

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
template <class T>
void foo(T x, int i);

template <class T>
typename boost::disable_if<boost::is_same<int, T> >::type
foo(int i, T x);

foo(1, 2); //calls the first

Here the library produces a "substitution failure" in the return type of the second overload, if T = int, removing it from the set of overload candidates.

In practice you should rarely run into situations like that.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...