Można rozważyć C++ szablony być interpretowane, funkcjonalny język programowania przebrany jako system generycznych. Jeśli to Cię nie przestraszy, powinno być :)
C# leki generyczne są bardzo ograniczone; możesz sparametryzować klasę na typie lub typach i użyć tych typów w metodach. Tak więc, aby wziąć przykład z MSDN, można zrobić:
public class Stack<T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
I teraz można zadeklarować Stack<int>
lub Stack<SomeObject>
i będzie ona przechowywać obiekty tego typu, bezpiecznie (czyli nie martwi się o umieszczenie w SomeOtherObject
przez błąd).
Wewnętrznie środowisko wykonawcze .NET specjalizuje się w wariantach dla typów podstawowych, takich jak int i wariant dla typów obiektów. Dzięki temu reprezentacja dla Stack<byte>
jest znacznie mniejsza niż na przykład z Stack<SomeObject>
.
Szablony C++ pozwalają podobne zastosowanie:
template<typename T>
class Stack
{
T *m_Items;
public void Push(const T &item)
{...}
public T Pop()
{...}
};
To wygląda podobnie na pierwszy rzut oka, ale istnieje kilka istotnych różnic. Po pierwsze, zamiast jednego wariantu dla każdego typu podstawowego i jednego dla wszystkich typów obiektów, istnieje jeden wariant dla dla każdego typu, który jest tworzony dla. To może być wiele rodzajów!
Następną ważną różnicą jest (w większości kompilatorów C++), że zostanie skompilowana w każdej jednostce tłumaczeniowej, w której jest używana. To może spowolnić kompilacje.
Innym interesującym atrybutem szablonów C++ jest to, że można je zastosować do rzeczy innych niż klasy - a gdy tak się stanie, ich argumenty mogą zostać automatycznie wykryte. Na przykład:
template<typename T>
T min(const T &a, const T &b) {
return a > b ? b : a;
}
Typ T zostanie automatycznie określony przez kontekst, w którym funkcja jest używana.
Atrybuty te można wykorzystać do dobrych celów kosztem zdrowia psychicznego. Ponieważ szablon C++ jest rekompilowany dla każdego typu, z którego jest używany, a implementacja szablonu jest zawsze dostępna dla kompilatora, C++ może wykonywać bardzo agresywne inlining na szablonach. Dodaj do tego automatyczne wykrywanie wartości szablonów w funkcjach i możesz dokonać anonymous pseudo-functions w C++, używając boost::lambda. Zatem wyrażenie jak:
_1 + _2 + _3
Generuje obiekt z poważnie przerażające typu, który ma operatora(), które dodaje się do jego argumentów.
Istnieje wiele innych ciemnych zakątków systemu szablonów C++ - jest to niezwykle potężne narzędzie, ale może być bolesne, aby myśleć, a czasami trudne w użyciu - szczególnie, gdy daje dwadzieścia stronicowy komunikat o błędzie. System C# jest znacznie prostszy - mniej wydajny, ale łatwiejszy do zrozumienia i trudniejszy do nadużywania.
Co za zbieg okoliczności, to jest mój blog na dzisiaj. http://blogs.msdn.com/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx –
to * ma * być dokładnym duplikatem. @Eric Lippert: Ooh, interesujące, da mu odczyt – jalf