Table of Contents

Partie 1 : Manipuler un ensemble d'arguments

TD12

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 :

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

Partie 2: Mesurer le temps passé par une fonction