Z tej listy tylko druga wprowadza niejednoznaczność, ponieważ funkcje - bez względu na to, czy są szablonami - nie mogą być przeciążane w oparciu o typ zwracany.
Można użyć dwóch pozostałych:
template<typename X> void func(X x, int y);
zostaną wykorzystane, jeżeli drugi argument wywołania jest int, np func("string", 10);
template<class X, class Y, class Z> void func(X x, Y y, Z z);
zostaną wykorzystane jeśli zadzwonisz func z trzech argumenty.
Nie rozumiem, dlaczego niektóre inne odpowiedzi wspominają, że funkcje szablonu i przeciążanie funkcji nie mieszają się. Z pewnością tak, i istnieją specjalne zasady, w jaki sposób wybrana jest funkcja wywołania.
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.)
Non-matrycy (lub "mniejszej matrycy") przeciążenie korzystnie szablonów, np
template <class T> void foo(T);
void foo(int);
foo(10); //calls void foo(int)
foo(10u); //calls void foo(T) with T = unsigned
Twój pierwszy przeciążenie z jednego parametru bez szablonu również podlega tej zasadzie.
Biorąc pod uwagę wybór między kilkoma szablonami, preferowane są bardziej wyspecjalizowane mecze:
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
można znaleźć bardziej formalny opis wszystkich reguł w tym samym rozdziale Standard (szablony funkcyjne)
I w końcu są sytuacje, w których dwa lub więcej przeciążeń byłoby niejednoznaczne:
template <class T> void foo(T, int);
template <class T> void foo(int, T);
foo(1, 2);
Tutaj połączenie jest niejednoznaczne, ponieważ obaj kandydaci są jednakowo wyspecjalizowani.
Możesz rozróżnić takie sytuacje za pomocą (na przykład) boost::disable_if
. Na przykład, możemy określić, że gdy T = int, potem drugi przeciążenie nie powinny być włączone jako kandydata przeciążeniem:
#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
Tu biblioteka produkuje „niepowodzenie podstawienie” w zwracanego typu drugiego przeciążeniem , jeśli T = int, usuwając go z zestawu przeciążonych kandydatów.
W praktyce rzadko należy wpadać w takie sytuacje.
Wszystkie poprzedzające znaki ';' są bezcelowe. Nie są one wymagane i powodują, że patrzenie na nie jest bardziej mylące. – Omnifarious