Mogę tylko wymyślić kilka różnic - oto kilka przykładów, które niekoniecznie powodują szkody (myślę). Ja pomijając definicje aby go terse
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
template <> int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses explicit specialization
// --- against ---
template <typename T> T inc(const T& t);
namespace G { using ::inc; }
int inc(const int& t);
namespace G { void f() { G::inc(10); } } // uses template
To dlatego, że specjalizacje nie są uznane przez wyszukiwania nazw, ale dopasowując argumentów, a więc za pomocą deklaracja zostanie automatycznie rozważyć później wprowadził specjalizację.
Następnie, oczywiście, nie można częściowo specjalizować szablonów funkcji.Przeciążenie jednak realizuje coś bardzo podobnego przez częściowego uporządkowania (za pomocą różnych typów teraz, aby mój punkt)
template <typename T> void f(T t); // called for non-pointers
template <typename T> void f(T *t); // called for pointers.
int a;
void e() {
f(a); // calls the non-pointer version
f(&a); // calls the pointer version
}
to nie byłoby możliwe z szablonu funkcja wyraźnej specjalizacji. Innym przykładem jest, gdy zaangażowane są referencje, które powoduje odliczenie szablon argument szukać dokładnego dopasowania typów zaangażowanych (baza modulo/pochodzące klasy relacje i constness):
template<typename T> void f(T const &);
template<> void f(int * const &);
template<typename T> void g(T const &);
void g(int * const &);
int a[5];
void e() {
// calls the primary template, not the explicit specialization
// because `T` is `int[5]`, not `int *`
f(a);
// calls the function, not the template, because the function is an
// exact match too (pointer conversion isn't costly enough), and it's
// preferred.
g(a);
}
polecam, aby zawsze używać przeciążenie, ponieważ jest bogatsze (pozwala na to coś takiego jak częściowa specjalizacja), a ponadto możesz umieścić funkcję w dowolnej przestrzeni nazw (choć wtedy nie jest to już nadmierne przeciążanie). Na przykład zamiast konieczności wyspecjalizowania std::swap
w przestrzeni nazw std::
, można umieścić przeciążenie swap
we własnym obszarze nazw i spowodować, aby był on wywoływalny przez ADL.
Cokolwiek robisz, nigdy nie mieszaj specjalizacji i przeciążaj, będzie to piekielnie brzydki jak this article wskazuje. Standard zawiera piękny akapit na temat tego, co to jest:
Umieszczenie deklaracji specjalizacji w szablonach funkcji, szablonach klas, funkcjach składowych szablonów klas, statycznych elementach danych szablonów klas, klasach członków szablonów klas, szablonach klas członków szablony klas, szablony funkcji członkowskich szablonów klas, funkcje składowe szablonów członków szablonów klas, funkcje składowe szablonów członków klas innych niż szablony, szablony funkcji członkowskich klas elementów szablonów klas itp. oraz umieszczanie deklaracji częściowej specjalizacji szablonów klas, szablonów klas członków klas bez szablonów, szablonów klas członkowskich szablonów klas itp., może wpływać na to, czy program jest dobrze uformowany zgodnie z relatywnym pozycjonowaniem jawnej decyzy specjalizacji aranżacje i ich punkty stawiania w jednostce tłumaczeniowej jak określono powyżej i poniżej. Pisząc specjalizację, uważaj na jej lokalizację; lub sprawić, że będzie on się kompilował, będzie próbą rozpalenia jej samopodpalenia.
Przegłosowałem pytanie, ponieważ jest to jeden z ciemnych obszarów w C++ (przynajmniej dla mnie)! – AraK
O co konkretnie prosisz? Tylko niektóre różnice lub niektóre przypadki, w których występuje zagrożenie? Na przykład, 'inc <> (10);' zachowuje się inaczej dla tych dwóch fragmentów - ale czy to właśnie chcesz usłyszeć? –