Moder C++ Översikt Mattias Flodi Geerisk programmerig vs OOP Stadard Template Library (STL) Partiell specialiserig Metaprogrammerig med templates Policybaserad desig Expressio templates Geerativ programmerig Geerisk programmerig vs OOP E titt i backspegel... C++ is ot a purely Object- Orieted Laguage. It is a laguage that supports Object-Orieted Programmig. Procedurell programmerig: Bestäm vilka procedurer du vill ha; aväd de bästa algoritmera du ka hitta. Modulär programmerig: Bestäm vilka moduler du vill ha; dela upp programmet så att data göms iom modulera. Dataabstraktio: Bestäm vilka datatyper du vill ha; tillhadahåll e full uppsättig operatioer för varje typ. Objektorieterad programmerig Geerisk programmerig Bestäm vilka klasser du vill ha Tillhadahåll e full uppsättig operatioer för varje klass Uttryck gemesamhet med arv Bestäm vilka algoritmer du vill ha Parameterisera dem så att de fugerar för e mägd olika typer och datastrukturer 1
Exempel: Byta plats på variabler void swap(t& a, T& b) T temp=a; a=b; b=temp; Exempel: E stackdatatyp template <typeame Type, it Size=100> class Stack Stack(); void push(type); Type pop(); private: Type values[size]; it top; template <typeame Type, it Size> void Stack<Type>::push(Type value) values[top++] = value; template <typeame Type, it Size> T Stack<Type>::pop() retur values[--top]; E stackdatatyp... Att täka på it mai() Stack<it> stk; stk.push(3); it popped_it = stk.pop(); Stack<strig> stk2; stk2.push("hello World"); strig popped_str = stk2.pop(); retur 0; E parameteriserad klass/fuktio kompileras om för varje y parameteruppsättig Kompilerig tar lägre tid Implemetatioe måste ofta fias i.h-file för att de ska vara tillgäglig för kompilator Vissa parameterval ka ge kompilerigsfel, adra ite Måga uika parameteruppsättigar ka leda till stora programfiler Stadard Template Library (STL) Ortogoal desig Utvecklades av Alex Stepaov och Meg Lee som ett mågårigt forskigsprojekt i Scheme, Ada och C++ Accepterades av stadardiserigskommité 1994 Tillhadahåller geeriska datatyper och algoritmer Implemeterar allt frå DOA och mer därtill... set list deque vector Iteratorer frot_isert_iterator ostream_iterator back_isert_iterator reverse_iterator raw_storage_iterator accumulate fid sort copy Algoritmer Behållare 2
Specialiserig Partiell specialiserig vector<bool> aväder oödigt mycket mie Ka effektiviseras med e skräddarsydd specialiserig class vector; template <> class vector<bool> Mer geerellt ka vi specialisera m.a.p. vissa parametrar. Detta går bara att göra med klasser. template <typeame Type, it Size> class Stack; // Matchar Stack<bool, N> för alla N template <it Size> class Stack<bool, Size> Partiell specialiserig... Partiell specialiserig... Kompilator möstermatchar för att hitta de mest passade implemetatioe class set; // Matchar alla typer som är pekare class set<t*> Äu mer komplicerat: class vector<pair<t, it> > Kaske käs ige... mis i ML? fu first x = il (head::tail) = head; Metaprogrammerig med templates Me, me... VARFÖR? Templates beskriver ett fuktioellt språk Ett program i språket körs uder kompilerige Ka aväda heltal och datatyper som argumet till fuktioer Går att implemetera if-the-else, listor, assertios, osv Metaprogrammerig är viktig för geerisk programmerig och för optimerig av program Ka t.ex. avädas för att ta reda på egeskaper hos parametrar template <typeame T1, typeame T2> class coversio static bool helper(t2); static double helper(...); static T1 maket1(); eum exists = (sizeof(helper(maket1())) == sizeof(bool)) 3
Exempel: Fiboacciserie If/The/Else-satser I ML: fu fib 0 = 0 fib 1 = 1 fib x = fib (x-1) + fib (x-2); Med templates: template <it X> struct fib eum Result = fib<x-1>::result + fib<x-2>::result template <> struct fib<0> eum Result = 0 template <> struct fib<1> eum Result = 1 template <bool Cod, typeame T, typeame U> struct Select; template <typeame T, typeame U> struct Select<true, T, U> typedef T Result; template <typeame T, typeame U> struct Select<false, T, U> typedef U Result; E lista med typer Beräkig av e listas lägd Defiieras rekursivt template <typeame T, typeame U> struct Typelist typedef T Head; typedef U Tail; Listas slut markeras med e tom datatyp, motsvarade MLs il struct NullType E typlista med olika heltalstyper: typedef Typelist<short, Typelist<it, Typelist<log, NullType> > > ItegerTypes; Görs rekursivt med NullType som basfall template <class TList> struct Legth; template <> struct Legth<NullType> eum Result = 0 template <class T, class U> struct Legth< Typelist<T, U> > eum Result = 1 + Legth<U>::Result Idexerig i e lista Metaprogram för optimerig På likade sätt template <class TList, it idex> struct TypeAt; template <typeame Head, typeame Tail> struct TypeAt<Typelist<Head, Tail>, 0> typedef Head Result; template <typeame Head, typeame Tail, it i> struct TypeAt<Typelist<Head, Tail>, i> typedef typeame TypeAt<Tail, i-1>::result Result; Exempel: Bubblesort för små arrayer void bubblesort(it* data, it N) for(it i = N-1; i>0; --i) for (it j = 0; j < i; ++j) if(data[j] < data[j+1]) swap(data[j], data[j+1]); 4
Mågfalde i mjukvarudesig Vi ka ite göra allt i ett grässitt! Problem: Det fis måga korrekta sätt att göra samma sak Igetig är helt rätt eller helt fel Olika problem kräver olika lösigar Hur ska ma skriva ett bibliotek så att alla ka aväda det? Mosterklasser är hopplösa att lära sig Explosiv programstorlek Lågsamma program Svårt att uderhålla Förlust av statisk typiformatio Om vi gör olika klasser för olika val? Policybaserad desig Försök göra flera olika klasser: SigleThreadedSmartPtr, MultiThreadedSmartPtr, RefCoutedSmartPtr, RefLikedSmartPtr,... Problem: Kombiatorisk explosio!... och mista förädrig är ett mastodotjobb The bottom lie: Desigvale måste kua göras av avädare, ite bara av skapare Moder C++, Adrei Alexadrescu E policy defierar e klass som styr utseede och beteede hos e aa klass Som template-parameter ka e policy vid kompilerig avgöra iehållet i e klass Exempel: Creator E policy för hur objekt ska skapas Implemeteras som e template-klass Tillhadahåller e create-fuktio template <class T> struct OpNewCreator static T* create() retur ew T; Fler val... template <class T> struct MallocCreator static T* create() void* buf = std::malloc(sizeof(t)); if(!buf) retur 0; retur ew(buf) T; template <class T> struct PrototypeCreator PrototypeCreator(T* pobj = 0) : pobj_(pobj) T* create() retur pobj_? pobj->cloe() : 0; T* get_prototype() retur pobj_; void set_prototype(t* pobj) pobj_ = pobj; private: T* pobj_; 5
Avädig E smart poiter desigval Template-klasser ka skickas som templateparametrar template <template <class T> class CreatioPolicy> class WidgetFactory : public CreatioPolicy<Widget>... typedef WidgetFactory<OpNewCreator> MyWidgetFactory; Hur ska klasse veta är objektet ska förstöras? - Referesräkig - Läkad lista - Djup kopierig -... Ska implicit typkoverterig tillåtas? Kotroll av pekarvärdet? Isåfall är? Hur rapportera fel? Allt detta är upp till avädare... Att täka på template < typeame T, template <class> class OwershipPolicy = RefereceCouted, class CoversioPolicy = DisallowCoversio, template <class> class CheckigPolicy = AssertCheck, > class SmartPtr; typedef SmartPtr<Widget, DeepCopy, AllowCoversio> WidgetPtr; Vi vill udvika virtuella fuktioer Destruktor bör vara protected När policies ärvs ka de berika grässittet Kopierig bör göras på per policy-basis Sträva efter ortogoala policies Ortogoalitet hos policies Expressio templates struct IsArray T& at(t* ptr, it idex) retur ptr[idex]; cost T& at(t* ptr, it idex) cost retur ptr[idex]; struct <typeame T> struct IsNotArray Uppfas oberoede ca 1995 av flera forskare; Todd Veldhuize, David Vadervoorde,... Ett sätt att skicka hela uttryck till fuktioer Jfr. LISPs och MLs lambdafuktioer Uttrycket ilieas i fuktioskroppe Aväds t.ex. för matris- och vektorberäkigar Ka ge 2-15 ggr sabbare program (!) 6
Exempel på avädig Hur fugerar det? it x=1; cout << (_1 * 2)(x); vector<it> v(10); vector<it*> vp(10); for_each(v.begi(), v.ed(), _1 += 2); trasform(v.begi(), v.ed(), vp.begi(), &_1); Överlagra operatorer så att de returerar ett uttrycksobjekt som represeterar uttrycket Datatype hos objektet ka beskriva ett parseträd för uttrycket sort(vp.begi(), vp.ed(), *_1 > *_2); for_each(vp.begi(), vp.ed(), cout << *_1 << edl); Geerativ programmerig Exempel: MTL vs BLAS Tillsammas blir dessa tekiker som små kodgeererare Mägde fuktioalitet växer expoetiellt med atalet geeriska klasser Kraftfull, specialiserad och högpresterade kod ka automatiskt växa ur ågra få, elemetära kompoeter BLAS: Basic Liear Algebra Subrouties - 154 495 ord, över 10,000 rutier MTL: Matrix Template Library - Gjordes som exjobb av Jeremy Siek - 15 184 ord - Sabbare - Lättare att aväda Istället för O(N*M) får vi O(N+M) MTL vs BLAS... Sammafattig Geerisk programmerig kompletterar OOP STL är ett geeriskt bibliotek som fis i stadarde Metaprogrammerig är ett kraftfullt och ödvädigt verktyg för geeriska bibliotek Policybaserad desig låter avädare forma biblioteke efter behov Med expressio templates, metaprogrammerig o.s.v. ka abstraktio OCH prestada uppås 7