This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
in204:tds:sujets:td6:part2 [2019/10/15 07:31] bmonsuez |
in204:tds:sujets:td6:part2 [2022/11/18 10:49] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Partie II – Vérifier que les exceptions sont bien capturées.====== | + | ====== Partie II – Spécialisation par contraintes ====== |
[[in204:tds:sujets:td6|TD6]] | [[in204:tds:sujets:td6|TD6]] | ||
+ | ===== Question n°1 ===== | ||
- | L'objet des questions suivantes est de pouvoir vérifier au moment de la compilation que les exceptions sont bien capturées ou bien que seules les exceptions indiquées sont supposées être déclencheés (cf. [[in204:cpp:syntax:exceptions:contract||les annotations relatives aux exceptions]]). | + | Nous considérons toujours notre code affichant le contenu d'un conteneur tel que défini dans la [[in204:tds:sujets:td6:part1|première partie]]. |
- | ===== Question n°1 ===== | + | <code cpp> |
+ | template<typename containerT, typename charT, typename traits = std::char_traits<charT>> | ||
+ | std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& aStream, const containerT& aContainer) | ||
+ | { | ||
+ | aStream << "{"; | ||
+ | auto end = aContainer.end(); | ||
+ | for(auto it = aContainer.begin(); it != end;) | ||
+ | { | ||
+ | aStream << *it ++; | ||
+ | if(it != end) | ||
+ | aStream << ", "; | ||
+ | } | ||
+ | aStream << "}"; | ||
+ | } | ||
+ | </code> | ||
- | L’exception ''division_by_zero'' peut être levée par la fonction ''divide''. Ajouter cette information à la fonction ''divide''. | + | ==== Question n°1.1 ===== |
- | ===== Question n°2 ===== | + | |
- | Compilez votre programme, que constatez-vous ? | + | Déterminer ce qui va caractériser un conteneur pouvant être pris comme argument par la fonction précédente ? |
- | ===== Question n°3 ===== | + | <hidden Correction> |
+ | |||
+ | En fait, il est attendu que le conteneur fournisse deux méthodes : | ||
+ | |||
+ | * `begin()`: retournant un itérateur marquant le début de la séquence, | ||
+ | * `end()`: retournant un itérateur marquant le fin de la séquence. | ||
+ | |||
+ | L'itérateur qui est retourné doit supporter : | ||
+ | * l'accès en lecture des données stockées dans le conteneur, | ||
+ | * le parcours en avant. | ||
+ | |||
+ | Il n'a pas besoin de supporter le multipasse. | ||
+ | |||
+ | </hidden> | ||
+ | |||
+ | |||
+ | ==== Question n°1.2 ===== | ||
+ | |||
+ | Implanter un concept qui permet de formaliser les exigences que vous venez de formuler ? | ||
+ | |||
+ | <hidden Correction> | ||
+ | <code cpp> | ||
+ | template<typename T> | ||
+ | concept Browsable = requires (const T& a) | ||
+ | { | ||
+ | { a.begin() } -> std::forward_iterator; | ||
+ | { a.end() } -> std::forward_iterator; | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
+ | |||
+ | ==== Question n°1.3 ===== | ||
+ | |||
+ | Ajouter les contraintes à l'opérateur %%<<%% qui a été défini pour un conteineur. | ||
+ | |||
+ | <hidden Correction> | ||
+ | <code cpp> | ||
+ | template<typename containerT, typename charT, typename traits = std::char_traits<charT>> | ||
+ | requires Browsable<containerT> | ||
+ | std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& aStream, const containerT& aContainer) | ||
+ | { | ||
+ | aStream << "{"; | ||
+ | auto end = aContainer.end(); | ||
+ | for(auto it = aContainer.begin(); it != end;) | ||
+ | { | ||
+ | aStream << *it ++; | ||
+ | if(it != end) | ||
+ | aStream << ", "; | ||
+ | } | ||
+ | aStream << "}"; | ||
+ | return aStream; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | |||
+ | ==== Question n°1.4 ===== | ||
+ | |||
+ | Introduisez une implantation de l'opérateur `<<` qui pour tout type affiche 'NONE'. | ||
+ | |||
+ | <hidden Correction> | ||
+ | <code cpp> | ||
+ | template<typename T, typename charT, typename traits = std::char_traits<charT>> | ||
+ | std::basic_ostream<charT, traits>& operator << (std::basic_ostream<charT, traits>& aStream, const T& aContainer) | ||
+ | { | ||
+ | std::cout << "NONE"; | ||
+ | return aStream; | ||
+ | } | ||
+ | </code> | ||
+ | </hidden> | ||
+ | |||
+ | |||
+ | ===== Question n°2 ==== | ||
+ | |||
+ | Nous avons deux fonctions pour effectuer un tri, l'algorithme simple de tri que nous avons implanté et l'algorithme ``std::sort`` fourni par la STL. | ||
+ | |||
+ | Cependant notre algorithme fonctionne pour des itérateurs qui ne supportent pas l'accès indexé tandis que l'algorithme ``std::sort`` est un quicksort et nécessite un accès indexé mais qui est plus rapide. | ||
+ | |||
+ | Modifier le code de ``std::simple_sort`` pour appeller ``std::sort`` si jamais les itérateurs sont des itérateurs supportant l'accès direct (``std::random_access_iterator``). | ||
+ | |||
+ | <hidden Correction> | ||
+ | <code cpp> | ||
+ | template<typename iterator> | ||
+ | void simple_sort(iterator start, iterator end) | ||
+ | requires(std::forward_iterator<iterator> && ! std::random_access_iterator<iterator> && std::input_or_output_iterator<iterator>) | ||
+ | { | ||
+ | std::cout << "Insertion Sort\n"; | ||
+ | for(;start != end; start ++) | ||
+ | { | ||
+ | auto it = start; it++; | ||
+ | for(;it != end; it ++) | ||
+ | { | ||
+ | // Compare si les deux elements sont dans le bon ordre. | ||
+ | if (*start > *it) | ||
+ | std::swap(*start, *it); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | template<typename iterator> | ||
+ | void simple_sort(iterator start, iterator end) | ||
+ | requires(std::random_access_iterator<iterator> && std::input_or_output_iterator<iterator>) | ||
+ | { | ||
+ | std::cout << "Quicksort\n"; | ||
+ | return std::sort(start, end); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | Et nous exécutons le code suivant : | ||
+ | |||
+ | <code cpp> | ||
+ | { | ||
+ | std::list<int> l = {1, 7, 3, 4, 9, 2, 5}; | ||
+ | std::vector<int> v(l.begin(), l.end()); | ||
+ | simple_sort(l.begin(), l.end()); | ||
+ | std::cout << l << std::endl; | ||
+ | simple_sort(v.begin(), v.end()); | ||
+ | std::cout << v << std::endl; | ||
+ | </code> | ||
+ | |||
+ | qui génèrera la sortie suivante: | ||
+ | <code> | ||
+ | Insertion Sort | ||
+ | {1, 2, 3, 4, 5, 7, 9} | ||
+ | Quicksort | ||
+ | {1, 2, 3, 4, 5, 7, 9} | ||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
- | Ajoutez les informations complémentaires à votre programme pour pouvoir compiler le programme ? | ||