Šablon metaprogramiranja
Šablon metaprogramiranja (TMP) je tehnika metaprogramiranja u kojoj šablone koristi kompajler za generisanje privremenog izvornog koda, koji je pripojen kompajleru sa ostatkom izvornog koda, a zatim sastavljen. Izlaz ovih šablona uključuje kompiliranja konstante, strukture podataka i kompletne funkcije. Korišćenje šablona može se posmatrati kao izvršenje kompiliranja. Tehnika se koristi od strane brojnih jezika, najpoznatiji su C++, ali takođe Curl, D, i XL.
Šablon metaprogramiranja je, u izvesnom smislu, otkriven slučajno.
Neki drugi jezici podržavaju sličan, ako ne i više moćno kompiliranje objekata (kao što je Lisp), ali oni su van obima ovog člana.
Komponente šablona metaprogramiranja[uredi | uredi izvor]
Korišćenje šablona kao tehnika metaprogramiranja zahteva dve odvojene operacije: šablon mora biti definisan, a definisan šablon mora biti instanciran. Definicija šablona opisuje opšti oblik generisanog izvornog koda, a instanciranje izaziva poseban set izvornog koda koji se generiše iz generičkog oblika u šablon.
Šablon metaprogramiranja je Tjuringova potpunost, što znači da svako ekspresno izračunavanje računarski program može da izračuna, u nekom obliku, od strane šablona metaprograma.[1]
Šabloni se razlikuju od makroa. Makro, što je takođe odlika kompiliranja jezika, generiše kod u-liniji koristeći manipulaciju teksta i zamenu. Makro sistemi često imaju ograničene sposobnosti kompiliranja procesa protoka i obično nemaju svest o semantici i tipu sistema njihovog pratioca jezika (izuzetak treba da budu Lisp makroi, koji su napisani u samom Lisp-u i uključuju manipulaciju i zamenu Lisp koda predstavljen kao struktura podataka nasuprot tekstu). Šabloni metaprogramiranja nemaju promenljive varijable- da se, bez promenljive može promeniti vrednost nakon što je inicijalizovana, stoga šablon metaprogramiranja može se posmatrati kao oblik funkcionalnog programiranja. U stvari, mnogi šabloni implementacije sprovode kontrolu protoka samo kroz rekurzije, kao što se vidi na primeru.
Korišćenje šablona metaprogramiranja[uredi | uredi izvor]
Iako se sintaksa šablona metaprogramiranja obično veoma razlikuje od programskog jezika sa kojim se koristi, ima praktične koristi. Neki uobičajeni razlozi da koriste šablone su da sprovedu generičko programiranje (izbegavajući delove koda koji su slični, osim nekih manjih varijacija) ili da vrši automatsku optimizaciju kompiliranja kao što rade nešto jednom u kompajliranju a ne svaki put da se program vodi - na primer, tako što kompajler odmotava petlje da eliminiše skokove i tačke petlje dekrementira kad god se izvršava program.
Kompiliranje klasa generacija[uredi | uredi izvor]
Šta tačno "programiranje kompiliranjem" znači može se ilustrovati sa primerom faktorijel funkcija, koja u šabonlu C ++ može biti pisana korišćenjem rekurzije na sledeći način:
unsigned int factorial(unsigned int n) {
return n == 0 ? 1 : n * factorial(n - 1);
}
// Примери коришћења:
// факторијал(0) би дало 1;
// факторијал(0) би дало 24.
Kod iznad će sprovesti u vreme izvršavanja za utvrđivanje faktorijalne vrednost literala 4 i 0. Pomoću šablona metaprogramiranja i šablona specijalizacije da obezbedi završni uslov za rekurzije, u faktorijalima koji se koriste u programu-ignoriše one faktorijale koji se ne koriste -mogu se izračunati kompajliranjem ovim kodom:
template <unsigned int n>
struct factorial {
enum { value = n * factorial<n - 1>::value };
};
template <>
struct factorial<0> {
enum { value = 1 };
};
// Примери коришћења:
// факторијал<0> :: вредност би дало 1;
// факторијал<0> :: вредност би дало 24.
Kod iznad izračunava faktorsku vrednost literala 4 i 0 u kompajliranju i koristi rezultat kao da su pre novosračunate konstante.
Da biste mogli da koristite šablone na ovaj način, prevodilac mora znati vrednost svojih parametara u kompajliranju, koji ima prirodni preduslov da faktorijalna <X> :: vrednost može se koristiti samo ako je X poznat u vreme kompilacije. Drugim rečima, X mora biti konstantna doslovno ili konstantan izraz.
U C++11, constexpr, način da se dozvoli prevodiocu da izvrši jednostavne izraze stalne, dodaje se. Koristeći constexpr, mogu se koristiti uobičajene rekurzivne faktorske definicije.[2]
Optimizacija kompiliranja koda[uredi | uredi izvor]
Faktorijal primer iznad je jedan od primera kompiliranja optimizacije koda da su svi faktorijalii korišćeni od strane programa unapred sastavljen i ubrizgava kao numeričke konstante na kompilaciji, štedi kako Run-time preko glave i memorije otiska. To je, međutim, relativno minorna optimizacija.
Kao drugo, još važnije, primer kompiliranja odmotavanja petlje, šablon metaprogramiranja se može koristiti za stvaranje dužina-n vektorskih časova (gde je n poznato na kompajliranje). Korist tokom tradicionalne dužine n vektora je da se petlje mogu odmotati, što dovodi do veoma optimiziranog koda. Kao primer, razmotrimo operatera dodataka. Dužine-N vektora dodatak može biti napisan kao
template <int length>
Vector<length>& Vector<length>::operator+=(const Vector<length>& rhs)
{
for (int i = 0; i < length; ++i)
value[i] += rhs.value[i];
return *this;
}
Kada prevodilac instancira predložak funkcije ako što je definisano gore, sledeći kod mogže biti proizveden:
template <>
Vector<2>& Vector<2>::operator+=(const Vector<2>& rhs)
{
value[0] += rhs.value[0];
value[1] += rhs.value[1];
return *this;
}
Optimizer kompajler treba da bude u stanju da razvijte for
petlje jer parametar šablon length
je konstanta u kompilaciji.
Međutim, uzeti oprez jer to može izazvati nadimanje koda, kao poseban odvijeni kod će se generisati za svaki 'N' (vektor veličine) možete instancirati.
Statički polimorfizam[uredi | uredi izvor]
Polimorfizam je zajednički standard programiranja objekata gde se izvedeni objekti mogu koristiti kao primeri njihovog osnovnog objekta, ali gde će biti pokrenute metode izvedenog objekata, kao u ovom kodu
class Base
{
public:
virtual void method() { std::cout << "Base"; }
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void method() { std::cout << "Derived"; }
};
int main()
{
Base *pBase = new Derived;
pBase->method(); // излаз "Derived"
delete pBase;
return 0;
}
gde će sva pozivanja na виртуелне
metode biti ona od najvažnijih izvedenih klasa. Ovo dinamičko polimorfno ponašanje je (obično) dobijeno stvaranjem virtuelne luk ap tabele za odeljenja sa virtuelnim metodama, tabele koje su prevalile vreme izvršavanja da identifikuju način da budu pozvane. Tako, run-time polimorfizam nužno podrazumeva izvršenje iznad glave.
Međutim, u mnogim slučajevima polimorfno ponašanje potrebno je da bude nepromenljivo i može biti određena u kompajliranju. Tada se Curiously Recurring Template Pattern (CRTP) može da koristi za postizanje statičkog polimorfizama, koji je imitacija polimorfizma u programskom kodu, ali koji je rešen u kompajliranju i na taj način ukida run-time virtuelne stolove. Na primer:
template <class Derived>
struct base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
};
struct derived : base<derived>
{
void implementation()
{
// ...
}
};
Ovde osnovna klasa šablona će iskoristiti činjenicu da funkcije kao članovi organia nisu instancirane, tek posle njihove izjave, i to će koristiti članovi izvedene klase u okviru svojih funkcija članica, preko upotrebe static_cast
, na kompilaciji generišući sastav objekta sa polimorfnim karakteristikama. Kao primer realnog-sveta koriste, CRTP se koristi u podsticaj iteratoru biblioteke.[3]
Još jedna slična upotreba je "Barton Nakmen trik", ponekad nazivaju "ograničen šablon proširenja", gde zajednička funkcionalnost može biti postavljena u osnovne klase koja se ne koristi kao ugovor već kao neophodna komponenta da se sprovede usklađenost ponašanja, dok minimizira lod redundantnost.
Prednosti i nedostaci šablona metaprogramiranja[uredi | uredi izvor]
- Kompiliranje naspram izvršenje vremena kompromis
- Ako se koristi veliki deo šablona metaprogramiranja, kompilacija može da postane spora; sekcija 14.7.1 aktuelnog standarda definiše okolnosti pod kojima se šabloni implicitno instanciraju. Definisanje šablona ne znači da će biti instanciran, a instanciranje klase šablona ne izaziva svoje definicije članicama da se instanciraju U zavisnosti od stila upotrebe, šabloni se mogu sastaviti bilo brže ili sporije nego što predaju valjani kod.
- Generičko programiranje
- Šablon metaprogramiranja omogućava programeri da se fokusira na arhitekturu i delegatu za kompajlersko stvaranje bilo kakve realizacije zahteva klijenta koda. Tako, šablon metaprogramiranja može da ostvari istinski generički kod, olakšavanje minimiziranje koda i bolje održavanje.
- Čitljivost
- Što se tiče C ++, sintaksa i idiomi šablona metaprogramiranja su ezoterične poređenju sa konvencionalnim C ++ programiranjem i šablon metaprogramiranja može biti veoma težak za razumevanje. [4][5]
Vidi još[uredi | uredi izvor]
- Metaprogramiranje
- Preprocesor
- Parametarski polimorfizam
- Izrazni šablon
- Refleksija
- Sastavite izvršenje funkcije vremena
Reference[uredi | uredi izvor]
- ^ Veldhuizen, Todd L. "C++ Templates are Turing Complete" Arhivirano na sajtu Wayback Machine (23. novembar 2015) (PDF). http://ubietylab.net/ Arhivirano na sajtu Wayback Machine (17. jun 2016).
- ^ Constexpr - Generalized Constant Expressions in C++11 - Cprogramming.com
- ^ Iterator Facade - 1.60.0
- ^ Czarnecki, K.; O’Donnell, J.; Striegnitz, J.; Taha, Walid Mohamed (2004).
- ^ Sheard, Tim; Jones, Simon Peyton (2002).
Literatura[uredi | uredi izvor]
- Alexandrescu, Andrei (2003). Modern C++ Design: Generic Programming and Design Patterns Applied. Addison-Wesley. ISBN 978-3-8266-1347-0.
- Abrahams, David; Gurtovoy, Aleksey (2005). C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond. Addison-Wesley. ISBN 978-0-321-22725-6.
- Clavel, Manuel (16. 10. 2000). Reflection in Rewriting Logic: Metalogical Foundations and Metaprogramming Applications. Cambridge University Press. ISBN 978-1-57586-238-5.
- Eisenecker, Ulrich W. (2000). Generative Programming: Methods, Tools, and Applications. Addison-Wesley. ISBN 978-0-201-30977-5.
- Vandervoorde, David; Josuttis, Nicolai M. (2003). C++ Templates: The Complete Guide. Addison-Wesley. ISBN 978-0-201-73484-3.
Dodatna literatura[uredi | uredi izvor]
- „Using C++ template metaprograms”. C++ Report. 7 (4): 36—43. maj 1995. Arhivirano iz originala 2009-03-04. g.
Spoljašnje veze[uredi | uredi izvor]
- "The Boost Metaprogramming Library (Boost MPL)".
- "The Spirit Library". (built using template-metaprogramming)
- "The Boost Lambda library". (use STL algorithms easily)
- "Template Haskell". (type-safe metaprogramming in Haskell)
- Bright, Walter. "Templates Revisited". (template metaprogramming in the D programming language)
- Koskinen, Johannes. "Metaprogramming in C++" Arhivirano na sajtu Wayback Machine (28. avgust 2014) (PDF).
- Attardi, Giuseppe; Cisternino, Antonio. "Reflection support by means of template metaprogramming" (PDF).
- Burton, Michael C.; Griswold, William G.; McCulloch, Andrew D.; Huber, Gary A. „Static data structures”. CiteSeerX 10.1.1.14.5881 .
- Amjad, Zeeshan. "Template Meta Programming and Number Theory".
- Amjad, Zeeshan. "Template Meta Programming and Number Theory: Part 2".
- "A library for LISP-style programming in C++".