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

Categories

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

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

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...