Szablon (D) – Wikipedia, wolna encyklopedia
Szablony (ang. template) są jednym z podejść do programowania uogólnionego. Szablony w D są bardzo podobne do szablonów i przestrzeni nazw w C++. Można im nadawać osobne funkcjonujące niezależnie nazwy przez co zachowują się wtedy jak sparametryzowana przestrzeń nazw. Szablony w D tworzy się następująco:
template Nazwa(T) { //deklaracje funkcji, klas, zmiennych int func(T arg) { return sizeof(arg); } }
Gdzie Nazwa jest szablonową przestrzenią nazw o parametrze T. Używanie szablonów w programie następuje poprzez poprzedzenie listy parametrów w nawiasach okrągłych wykrzyknikiem.
Nazwa!(long).func(10); Nazwa!(int[]).func(1,2,3,4,5,6,7,8,9,10);
Klasy szablonowe i funkcje
[edytuj | edytuj kod]Klasy i funkcje szablonowe można tworzyć na 2 sposoby.[1][2] Długi poprzez umieszczenie klasy/funkcji o nazwie takiej samej jak szablon lub w krótszy sposób poprzez umieszczenie listy parametrów zaraz za deklaracją nazwy klasy/funkcji.
class MojaKlasa(T) { // klasa szablonowa z parametrem T } int func(T)(T arg) { // funkcja szablonowa }
Użycie jest podobne do zwykłych szablonów, ale można pominąć wtedy przestrzeń nazw:
MojaKlasa!(int) a = new MojaKlasa!(int); func(52);
Zmienna liczba parametrów szablonu
[edytuj | edytuj kod]W D istnieje możliwość tworzenia szablonów z nieokreśloną liczbą parametrów[3], co może być w wielu przypadkach bardzo użyteczne.
real sum(T...)(T args) { real ret = 0; foreach(a; args) ret += a; return ret; // zwróci sumę wszystkich argumentów jako liczbę rzeczywistą }
Użycie takiej funkcji jest o tyle proste, że nie trzeba wymieniać wszystkich argumentów:
sum(12,34434.42432,32453235432,21421,124,2424.2342,214124.5);
Metaprogramowanie z wykorzystaniem szablonów
[edytuj | edytuj kod]Metaprogramowanie w D jest znacznie ułatwione dzięki zastosowaniu instrukcji warunkowej kompilacji "static if". Przykładowo szablon liczący silnię z podanej liczby[4] (por. silnia w czasie kompilacji (c++)):
template Silnia(N) { static if(N==0) // statyczny if enum Silnia = 1; else enum Silnia = Silnia!(N-1)*N; }
Gdzie N to parametr określający liczbę z jakiej liczymy silnię.
Kompilatory D pozwalają również na wykonywanie funkcji "czystych" (ang. pure) w czasie kompilacji, tak więc powyższy szablon można zastąpić zwykłą funkcją:
int silnia(int n) { return (n == 1) ? 1 : n * silnia(n-1); } static int x = silnia(5);
Wartość zmiennej x będzie obliczona w czasie kompilacji.
Można to sprawdzić, korzystając z możliwości D operowania na ciągach znaków w czasie kompilacji oraz z instrukcji kompilatora pragma(msg,)[5]:
template itoa(long i) { static assert (i > 0); static if (i < 10) const char[] itoa = "" ~ cast(char)(i + '0'); else const char[] itoa = itoa!(i / 10) ~ itoa!(i % 10); } pragma(msg, itoa!(silnia(6));
Ponieważ szablon itoa parametryzowany jest wartością typu long, użyta jest instrukcja warunkowej kompilacji static assert, może ona być pominięta, jeśli typ argumentu i zostanie zmieniony na ulong.
Instrukcja ta spowoduje przerwanie kompilacji, jeśli podany argument jest liczbą ujemną.
Przypisy
[edytuj | edytuj kod]- ↑ Templates D 1.0 (Class Template Declaration). [dostęp 2010-06-03]. (ang.).
- ↑ Templates D 1.0 (Function Template Declaration). [dostęp 2010-06-03]. (ang.).
- ↑ Variadic Templates D 1.0. [dostęp 2010-06-03]. (ang.).
- ↑ Templates Revisited D 1.0. [dostęp 2010-06-03]. (ang.).
- ↑ Factorial (Rosetta Code). [dostęp 2010-06-03]. (ang.).
Bibliografia
[edytuj | edytuj kod]- Templates D 1.0. [dostęp 2010-06-03]. (ang.).
- Templates D 2.0. [dostęp 2010-06-03]. (ang.).