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]
  1. Templates D 1.0 (Class Template Declaration). [dostęp 2010-06-03]. (ang.).
  2. Templates D 1.0 (Function Template Declaration). [dostęp 2010-06-03]. (ang.).
  3. Variadic Templates D 1.0. [dostęp 2010-06-03]. (ang.).
  4. Templates Revisited D 1.0. [dostęp 2010-06-03]. (ang.).
  5. Factorial (Rosetta Code). [dostęp 2010-06-03]. (ang.).

Bibliografia

[edytuj | edytuj kod]