User Tools

Site Tools


in204:tds:sujets:td12_2023:part1

Partie 1 : Manipuler un ensemble d'arguments

Question 1

Ecrire une fonction print qui prend un nombre libre d'entiers en paramètres et qui affiche ces entiers sur la console.

Pour ce faire, nous vous conseillons d'autiliser la classe std::initializer_list<T> comme argument de la fonction.

Un std::initializer_list<T> permet d'accéder à la une liste de valeurs de type T qui est écrit sous la forme suivante :

std::initializer_list<int> list_of_values = {1, 3, 4, 2 };

Cette liste de valeur n'est pas modifiable. Il est seulement possible de la lire en lecture comme un containeur classique. Les fonctions begin(), end() ainsi que size() permettent d'accéder aux valeurs stockées dans la liste.

Correction

Correction

void print(std::initializer_list<int> arguments)
{
    auto it = arguments.begin(),
        end_it = arguments.end();
    if (it != end_it)
    {
        std::cout << *it;
        while (++it != end_it)
            std::cout << ", " << *it;        
    }
}

Question 2

Généraliser cette fonction à d'autres types que les types entiers.

Cette fois-ci, nous attaquons les choses un peu plus complexes. En effet, pour cela, vous allez utiliser les packs de paramètres des fonctions et des classes templatées.

Quand nous écrivons :

  • template<class …Args> f(Args… arguments), cela signifie que la fonction prend comme arguments un ensemble d'arguments qui ont des types différents. La variable arguments fait référence à l'ensemble des valeurs ayant chacun un type différent, c'est pour cela que l'on parle de pack de paramètres. Attention, il n'est pas possible d'accéder aux données individuelles présentes dans le pack de paramètres.
  • l'opérateur sizeof…(Args) permet d'obtenir le nombres d'arguments passés à la fonction ou spécifié comme paramètres de la classe.
  • En fait, les packs de paramètres servent à être passés directement à une fonction. Ainsi nous pouvons écrire le code suivant :
void number_of_args() { std::cout << "no arguments"; }
template<classT> void number_of_args(T) { std::cout << "one argument"; }
template<classT1, class T2> void number_of_args(T1, T2) { std::cout << "two arguments"; }
 
template<class ...Args>
void func(Args... arguments)
{
    return number_of_args(arguments...);
}

va appeller en fonction du nombre d'arguments l'une des fonctions number_of_args.

Nous pouvons désormais imaginer une approche récursive pour compter le nombre d'arguments en implantant le code suivant :

template<class ...Args>
int number_of_args(T first_argument, Args... arguments)
{
    return 0;
}
template<class T, class ...Args>
int number_of_args(T first_argument, Args... arguments)
{
    return 1 + number_of_args(arguments);
}

L'appel de la fonction number_of_args qui suit :

    std::cout << number_of_args(1, "e", 2.0, 'c') << "\n";

retournera 4.

Question 2.1

Expliquer comment le code a été exécuté ?

Correction

Correction

le code number_of_args(1, “e”, 2.0, 'c') correspond à appeller la fonction :

number_of_args<int, const char*, double, char> number_of_args(1, “e”, 2.0, 'c') avec :

  • T = int,
  • Args.. = const char*, double, char

Cette fonction appelle récursivement 1 + number_of_args(“e”, 2.0, 'c'), soit

number_of_args<const char*, double, char> number_of_args(“e”, 2.0, 'c') avec :

  • T = const char*,
  • Args.. = double, char

puis ensuite 1 + number_of_args(2.0, 'c'), soit

number_of_args<double, char> number_of_args(“e”, 2.0, 'c') avec :

  • T = double,
  • Args.. = char

puis ensuite 1 + number_of_args('c'), soit

number_of_args<char> number_of_args(“e”, 2.0, 'c') avec :

  • T = char,
  • Args.. =

puis ensuite 1 + number_of_args(), soit

number_of_args<char> number_of_args() avec :

  • Args.. =

qui elle retroune 0.

Ce qui génère bien le résultat 4.

Question 2.2

En vous inspirant du code précédant, proposer une fonction print qui prend un nombre variable de paramètres qui peuvent avoir des types différents et qui imprime cette liste de paramètres sur la console.

Correction

Correction

template<class T>
void print(T first_argument)
{
    std::cout << first_argument;
}
 
template<class T, class ...Args>
void print(T first_argument, Args... arguments)
{
    std::cout << first_argument;
    if (sizeof...(Args) > 0)
        std::cout << ", ";
    print(arguments...);
}

Navigation

in204/tds/sujets/td12_2023/part1.txt · Last modified: 2023/12/05 09:19 by bmonsuez