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 containeur.
<hidden Correction>
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;
}
</hidden>
===== Question n°1.4 =====
Introduisez une implantation de l'opérateur `<<` qui pour tout type affiche 'NONE'.
<hidden Correction>
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;
}
</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 supporte par 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_iterator``).
<hidden Correction>
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);
}
Et nous exécutons le code suivant :
{
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;
qui génèrera la sortie suivante:
Insertion Sort
{1, 2, 3, 4, 5, 7, 9}
Quicksort
{1, 2, 3, 4, 5, 7, 9}