Domácí úkoly Pokročilé programování v C++ LS 2015/2016 1
DÚ 1 continuation termín: pondělí 14.3. 23:59 2
DÚ 1 - continuation continuation f(int argc, char * * argv) { if (!argc) return done(); std::cout << ">>" << argv[ 0] << std::endl; return cont( f, argc - 1, argv + 1); int main(int argc, char * * argv) { run( cont( f, argc, argv)); Jednoduché použití typ continuation funkce cont vrací continuation obsahující pokyn zavolat danou funkci s danými parametry zadaná funkce vrací další continuation jako pokyn pokračovat dalším voláním funkce done vrací prázdné continuation funkce run spouští zadané funkce tak dlouho, dokud nejsou vyčerpány pokyny return 0; 3
DÚ 1 - continuation continuation k(const std::string & s) { std::cout << "\"" << s << "\"" << std::endl; return done(); continuation h(int argc, char * * argv) { auto s = cont(k, "The arguments are..."); for (int i = 0; i < argc; ++i) { s &= cont(k, argv[i]); return std::move(s) & cont(k, "The end"); Složitější použití typ continuation podporuje zřetězení formou operátorů & a &= pokyny vlevo budou provedeny před pokyny vpravo nepodporuje kopírování, každý vytvořený pokyn může být proveden pouze jednou nutno používat move funkce run spouští zadané funkce tak dlouho, dokud nejsou vyčerpány pokyny pokynů může být více najednou pokyny vrácené z právě ukončené funkce mají přednost před staršími pokyny 4
DÚ 1 - continuation Příklad odjinud konstruktor std::thread (zjednodušeno) template< class Function, class... Args > explicit thread( Function&& f, Args&&... args ); Creates new std::thread object and associates it with a thread of execution. First the constructor copies/moves all arguments (both the function object f and all args...) to thread-accessible storage as if by the function: template <class T> typename std::decay<t>::type decay_copy(t&& v) { return std::forward<t>(v); Let's refer to value_args as t1, t2,..., tn, where N is sizeof...(value_args) and value_args is the result of calling decay_copy as defined above. The following code will be run in the new thread: f(t1, t2,..., tn); t1, t2,..., tn jsou rvalue (pozn. překladatele) 5
DÚ 1 - continuation Příklad odjinud pokračování The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref). void f1(int n); void f2(int& n); void test() { int n = 0; std::thread t2(f1, n); // pass by value std::thread t3(f2, std::ref(n)); // pass by reference t3.join(); // ensure that t3 is finished before n dies std::cout << n; The copy constructor is deleted; threads are not copyable. 6
DÚ 1 - continuation Rozbalení tuple do parametrů funkce std::index_sequence<i1,...,in> je šablona parametrizovaná posloupností čísel std::make_index_sequence<n> == std::index_sequence<0,1,...,n-1> tyto indexy jsou zapotřebí jako parametry funkce get pro přístup do šablony trik: pomocná funkce s přídavným argumentem, u nejž je zajímavý pouze typ template<typename Func, typename Tup, std::size_t... index> void invoke_helper(func&& func, Tup&& tup, std::index_sequence<index...>) { func(std::get<index>(std::forward<tup>(tup))...); template<typename Func, typename Tup> void invoke(func&& func, Tup&& tup) { const auto Size = std::tuple_size<typename std::decay<tup>::type>::value; invoke_helper(std::forward<func>(func), std::forward<tup>(tup), std::make_index_sequence<size>{); 7
Kritéria hodnocení včasnost za nedodržení termínu body prudce dolů přeložitelnost přeložitelné bez chyb a (pokud možno) warningů kompatibilní s vzorem použití (rozhraní je pevné) multiplatformnost nezávislost na OS, bitovosti, překladači - vyzkoušejte i gcc32/vs64 stabilita rozhodně vyzkoušejte všechna možná přípustná data a typy kultura kódu pravidla, moudra, dobré zvyky, udržovatelnost, estetika, čitelnost odevzdávací formality a konvence názvy a struktura souborů, komentáře 8
Soubory DÚ 1 v du1.zip najdete 3 soubory du1test.cpp kód používající vaše řešení - neměňte - zachovat rozhraní! můžete (velmi doporučeno!) přidat vlastní testy du1continuation.cpp, du1continuation.hpp sem doplňte kód a hlavičkový soubor vašeho řešení soubory nepřejmenovávejte na začátek každého souboru vložte komentář typu // du1continuation.hpp // Karel Vomacka NPRG051 2015/2016 vaše řešení vložte do Grupíčku - neposílejte emailem! správné soubory do správných sloupečků! 9
DÚ 2 PersistentMap termín: pondělí 11.4. 23:59 10
DÚ 2 - PersistentMap PersistentMap Podobný kontejner jako std::map Jednotlivé klíče a hodnoty se ukládájí do souborů Datová struktura je generická, tj. třída je šablona, která má dva parametry: typ klíče typ uložené struktury v souboru Naimplementujte základní operace: operator[] iterator find (const key_type& k); + const varianta std::pair<iterator, bool> insert(const std::pair<const Key, FileType>& val); size_type erase(const key_type& k); iterátory begin(), end(), const_begin(), const_end() Kontejner umožňuje použití const iteratorů a implementuje move operace (move konstruktory a move přiřazovací operator) na dílčích strukturách iterátory,... Kopírování, přesouvání samotné persistentní mapy není definováno 11
DÚ 2 - PersistentMap using pm_t = PersistentMap<string,string>; pm_t mymap("testdirectory"); mymap["file20.txt"] = "content 20"; mymap["file10.txt"] = "content 10"; mymap["file15.txt"] = "content 15"; string f10 = mymap["file10.txt"] std::string file; std::string content; for (auto& i : mymap) { tie(file, content) = i; cout << file << ": " << content << endl; Jednoduché použití inicializace PersistentMapy (PM) cestou ke složce s daty operátor hranatých závorek se chová obdobně jako u std::map umožňuje číst hodnotu z mapy pokud hodnota s daným indexem neexistuje, pak je vytvořena nová položka se stejným indexem umožňuje upravit hodnotu v PM pokud je složka TestDirectory před spuštěním programu prázdná, pak po spuštění programu má následující obsah: file10.txt - content 10 file15.txt - content 15 file20.txt - content 20 12
DÚ 2 - PersistentMap using key_type =... using mapped_type =... using value_type =... using reference =... using const_reference =... using pointer =... using const_pointer =... iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; const_iterator cbegin() const; const_iterator cend() const; for (pm_t::iterator it = mymap.begin(); it!= mymap.end(); ++it) { Iterátory kontejner umožňuje přístup k položkám skrze iterátory Bidirectional Iterátory nutné definovat veřejné aliasy datových typů procházení položek v kontejneru pomocí iterátorů v setříděném pořadí nutné načíst všechny soubory v dané složce (nerekurzivně) tie(file, content) = *it; cout << file << ": " << content << endl; je možné použít algoritmy z STL např.: std::copy 13
DÚ 2 - PersistentMap Problémy Jak pracovat s různými datovými typy e.g. PersistentMap<int, UserDefinedType>, PersistentMap<string, vector<string>> použijte definované trait třídy: KeySerializationTrait, FileTypeSerializationTrait výchozí implementace využívá std::stringstream k serializaci a deserializaci uživatel PM musí poskytnou vhodnou serializaci / deserializaci svých datových typů formou specializací šablon KeySerializationTrait, FileTypeSerializationTrait template <typename T> struct KeySerializationTrait { static string Serialize(const T& t) {stringstream ss; ss << t; return ss.str(); static T Deserialize(const string& str) { T tmp; stringstream(str) >> tmp; return tmp; ; template <typename T> struct FileTypeSerializationTrait { static void Serialize(ostream& filestream, const T& item) { filestream << item; static T Deserialize(istream& filestream) { T tmp; filestream >> tmp; return tmp; ; 14
DÚ 2 - PersistentMap Problémy Procházení souborů ve složce API funkce operačního systému nejnovější verze knihovny Boost (1.60.0) Invalidace iterátorů funkce PM (operator[], find, insert, erase, begin, end, const_begin, const_end) iterátory stejně jako v std::map neinvalidují vyjímku tvoří pouze erase, který invaliduje iterátory ukazující na mazanou položku Ukládání do / načítání ze souborů k uloženým datům na disku lze přistupovat skrze nově inicializovanou PM po skončení platnosti instance PM, musí být data již zapsána na disk nesmí ovlivnit chování chování iterátorů 15
DÚ 2 - PersistentMap Problémy Jak odchytit čtení z/ zápis do položky (VOLITELNÉ není nutné pro splnění DÚ) operátor[] u std::map vrací referenci na std::map::value_type ( tedy std::map::value_type&) není podmínkou, aby PM vracela referenci na value_type lze vrátit instanci proxy třídy, která se stará o uložení / načtení správné hodnoty implementace implicitních konverzních operátorů implementace konstruktorů, přiřazovacích operátorů platnost proměné může ovlivňovat její použití operátor[] se musí chovat stejně jako v std::map řešení je dobré v okamžiku kdy více instancí sdílí stejné úložiště dat 16
DÚ 2 - PersistentMap UPDATE Předpokládejte, že datový typ, se kterou je PM použita, má výchozí konstruktor a je kopírovatelný Nelze předpokládat, že data uložená na disku se celá vejdou do paměti Předpokládejte, že položka PM žije po celou dobu existence objektů proxy třídy, které na ní odkazují. tj. položka by měla být uložena v okamžiku, kdy poslední odkazující objekt proxy třídy byl destruován případ int& var = pm_instance[key]; var =...; tedy nenastane Ošetření chybových stavů lze řešit funkcí, která vrací úspěšnost poslední provedené operace 17
Kritéria hodnocení včasnost za nedodržení termínu body prudce dolů přeložitelnost přeložitelné bez chyb a (pokud možno) warningů kompatibilní s vzorem použití (rozhraní je pevné) multiplatformnost nezávislost na OS, bitovosti, překladači - vyzkoušejte i gcc32/vs64 stabilita rozhodně vyzkoušejte všechna možná přípustná data a typy kultura kódu pravidla, moudra, dobré zvyky, udržovatelnost, estetika, čitelnost odevzdávací formality a konvence názvy a struktura souborů, komentáře 18
Soubory DÚ 2 PersistentMap v du2_persistentmap.zip najdete 3 zdrojové soubory Main.cpp kód používající vaše řešení - neměňte - zachovat rozhraní! můžete (velmi doporučeno!) přidat vlastní testy PersistentMap.cpp, PersistentMap.hpp sem doplňte kód a hlavičkový soubor vašeho řešení soubory nepřejmenovávejte na začátek každého souboru vložte komentář typu // PersistentMap.hpp // Karel Vomacka NPRG051 2015/2016 vaše řešení vložte do Grupíčku - neposílejte emailem! správné soubory do správných sloupečků! knihovna Boost pokud plánujete použít knihovnu boost, skripty pro její kompilaci najdete ve složce lib 19