IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Valeurs par défaut des paramètres variadiques


Sujet :

C++

  1. #1
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut Valeurs par défaut des paramètres variadiques
    Bonjour,

    je viens de me décider à passer à la nouvelle norme et je regarde en ce moment le paramétrage variadique de classe. Je me demande dans quelle mesure il est possible d'attribuer des valeurs par défaut à ces petites bêtes. Je ne vois pas trop comment cela pourrait être possible et à ma connaissance on ne peut pas s'en sortir avec la spécialisation partielle vu que les valeurs par défaut ne sont pas autorisées dans ce cas.

    Quelle est la solution?

    Merci!

  2. #2
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Mmmh... s'en passer ?
    La puissance des variadics c'est qu'ils peuvent être vides.
    Dans la spécialisation où le paramètre variadic est vide, libre à toi de faire comme si on avait passé les valeurs par défaut.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    template <class ... Args>
    struct A;
     
    template <class T1, class ... Args>
    struct A<T1, Args...>
    {
        using type = T1;
    }
     
     
    template <>
    struct A<>
    {
        using type = unsigned int;//ou ce que tu veux
    }
    edit: après si on souhaite avoir plusieurs paramètres par défaut, on peut faire un empilement de cette technique, mais ça devient très lourd...

    edit2: et comme il y a plusieurs façon de faire (comme d'habitude), on peut également jouer avec l'opérateur sizeof... et quelques type_traits :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <class ... Args>
    struct A
    {
        using type0 = std::conditional<(sizeof...(Args)> 0), std::tuple_element<0, std::tuple<Args...>>::type, int>;
     
        using type1 = std::conditional<(sizeof...(Args)> 1), std::tuple_element<1, std::tuple<Args...>>::type, unsigned int>;
     
        using type2 = std::conditional<(sizeof...(Args)> 2), std::tuple_element<2, std::tuple<Args...>>::type, short>;
    }
    Voilà, je pense que le dernier code correspond à ce que tu cherches à faire...

    edit3: oui je sais il m'a fallu pas mal d'edit avant d'écrire une solution convenable

  3. #3
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonjour,

    merci pour ta réponse. En fait, j'ai du mal m'exprimer, je voulais bien parler de valeur par défaut, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template<typename TYPE,size_t SIZE=0> class Array{TYPE val[SIZE];};
    template<typename TYPE> class Array<TYPE,0>{TYPE* val;}
    qui permet de gérer des allocations statiques et dynamiques. C'est pratique de mettre une valeur par défaut ici (en l'occurence zéro), cela permet d'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Array<double,10> toto; // statique
    Array<double> titi; // dynamique
    plutôt que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Array<double,10> toto; // statique
    Array<double,0> titi; // dynamique

  4. #4
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Imaginons qu'on puisse écrire template <size_t ... sizes = {2,3,4,5}>
    Comment l'utiliserais-tu ?

  5. #5
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Comme je le dis dans mon premier post, cela n'a pas de sens. Mais j'aimerais émuler ce comportement.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Je te donne un exemple de ce que je fais déjà en espérant que ça ne biaise pas trop les réponses. Pour le moment, j'émule déjà en quelque sorte ce comportement de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    template<typename TYPE, template<typename,size_t...> class Policy>,size_t... SIZES> 
    class Array : public Policy<TYPE,... SIZES>
    {};
     
    template<typename TYPE, size_t SIZE=0> 
    class Policy1
    {
        TYPE val[SIZE];
    };
    template<typename TYPE> 
    class Policy1<TYPE,0>
    {
       size_t size;
       TYPE* val;
    };
     
    template<typename TYPE, size_t SIZE1,size_t SIZE2=0> 
    class Policy2
    {
        TYPE val[SIZE2];
    };
    template<typename TYPE,size_t SIZE1> 
    class Policy2<TYPE,SIZE1,0>
    {
       size_t size;
       TYPE* val;
    };
    Sauf que j'ai l'impression de gâcher : je me demande s'il n'y a pas plus intelligent avec les nouveaux outils à disposition.

  7. #7
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Dans ce cas on reprend mon 2e exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
     
    namespace utils
    {
     
    template <size_t pos, class T, T ... args>
    struct getv;
     
    template <size_t pos, class T, T t1, T ... args>
    struct getv<pos, T, t1, args...>
    {
        static const T value = pos ? getv<pos - 1, T, args...>::value : t1;
    };
     
    }
     
     
    template <size_t ... sizes>
    struct A
    {
        static const size_t s0 = sizeof...(sizes) > 0 ? utils::getv<0, size_t, sizes...>::value : 0;
        static const size_t s1 = sizeof...(sizes) > 1 ? utils::getv<1, size_t, sizes...>::value : 0;
        static const size_t s2 = sizeof...(sizes) > 2 ? utils::getv<2, size_t, sizes...>::value : 0;
    };
    edit: p.s: j'ai répondu sans voir ton nouveau message

  8. #8
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Merci pour ta réponse, je pense que cela va m'aider.
    Je veux bien un petit commentaire de ton dernier code car il y a des éléments de syntaxe que je ne connais pas : que retourne sizeof... ?

  9. #9
    Membre éclairé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    434
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2010
    Messages : 434
    Points : 654
    Points
    654
    Par défaut
    Bonjour,

    Je trouve ce lien plutôt complet en espérant que tu trouve ton bonheur.

    Article c++ template variadic

  10. #10
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Voilà le petit commentaire :
    La première partie est tirée de ma bibliothèque standard personnelle (d'où le namespace utils), je reviendrai en détail sur le getv plus loin.

    La deuxième partie est la plus intéressante :
    On prend en paramètre de la struct un nombre indéfini de paramètres de type size_t, éventuellement aucun.
    Puis on définit les constantes statiques dont on va se servir par la suite et dont l'initialisation dépend des paramètres passés et des valeurs par défaut.
    Je n'ai défini que 3 constantes, mais c'est totalement arbitraire, on peut en définir un peu plus (ou un peu moins ).

    Pour les templates, les constexpr et les constantes statiques, les ternaires sont les formes de condition les plus pratique puisqu'elles sont comprises et assimilées par le compilateur comme une seule expression (contrairement à un if).
    La condition porte ici sur la taille du variadic. sizeof...(sizes) retourne le nombre d'éléments contenus dans le variadic. Il est à noter qu'il aurait tout à fait été possible d'implémenter cette fonctionnalité dans la STL sans en faire un élément du langage.
    Puis en fonction du résultat de la condition on affecte une valeur à la constante : si le paramètre a été spécifié dans le variadic (ie le variadic contient au moins assez d'éléments pour que la valeur s'y trouve), alors on lui donne la valeur spécifiée. Sinon, on lui donne la valeur par défaut (ici 0).

    On récupère ici la valeur du paramètre spécifié en faisant appel à getv, qui n'est donc pas standard, mais est un utilitaire qui pourrait pour moi se ranger dans cette catégorie (totalement sans dépendance, aucun #include requis).

    Passons donc à l'explication de getv, qui est un exemple de template récursif.
    Tout d'abord un petit point sur la première déclaration :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <size_t pos, class T, T ... args>
    struct getv;
    Cette déclaration est ici totalement superflue, mais c'est une habitude à prendre pour pouvoir faire des spécialisations de struct variadics.
    C'est la définition générale, qui serait difficile à implémenter ainsi. C'est pourquoi on la spécialise dans la 2e déclaration qui cette fois ci est une définition.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template <size_t pos, class T, T t1, T ... args>
    struct getv<pos, T, t1, args...>
    {
        static const T value = pos ? getv<pos - 1, T, args...>::value : t1;
    };
    Cette déclaration demande quand à elle au moins un argument t1 pour pouvoir se définir. Cet argument est suivi par un argument variadic, ce qui va permettre la récursion.
    Passons à la ligne intéressante, celle qui définit la constante value. Encore une fois, un ternaire. La condition porte cette fois-ci sur la position de l'élément que l'on souhaite récupérer. Si cette position est zéro, cela signifie que l'on cherche t1, c'est la terminaison du template récursif (j'y reviens plus tard). Sinon, on cherche un élément se trouvant dans args. On demande donc la valeur trouvée par getv appliqué à args seulement (note bien qu'on omet le paramètre t1, c'est très important, c'est ce qui fait la récursivité), tout en décrémentant la position puisqu'on a enlevé le premier paramètre de la liste, ce qui permettra à pos d'obtenir un jour la valeur zéro, qui est la terminaison (sinon le compilateur va grogner pour cause de récursivité infinie ).
    Lors de la terminaison, le compilateur n'ira pas chercher plus loin, puisqu'il a trouvé une valeur concrète pour value.

    Voilà, j'espère que c'est assez clair .

    P.S: je trouve pour ma part l'article en question très incomplet et même bizarre : que viennent faire là toutes ces élucubrations sur les ... ? Quid des templates récursifs ? Quid également des paramètres templates variadics de valeur ? Quid de l'utilisation normale de l'expansion ?

  11. #11
    Membre expérimenté
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Points : 1 685
    Points
    1 685
    Par défaut
    Bonsoir germinolegrand,

    j'ai mis un peu de temps à répondre car j'ai pris le temps de me pencher un peu plus sur la question. Ta deuxième solution est vraiment très intéressante et je la garde en tête pour plus tard mais je crois c'est finalement ta première solution qui m'a vraiment éclairé sur mon problème... de conception! N'étant pas encore très à l'aise avec les templates variadiques, j'ai complètement détourné le concept en voulant faire ce que je faisais avec l'ancienne norme (valeurs par défaut) avec la nouvelle norme. Avec les templates variadiques, les valeurs par défaut, telles que je les utilise pour séparer allocations statique et dynamique, n'ont tout simplement plus lieu d'être. C'est maintenant beaucoup plus simple puisque je peux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    template<typename TYPE,size_t... SIZES>
    class Tableau{};
     
    template<typename TYPE,size_t SIZE>
    class Tableau<TYPE,SIZE>
    {
        TYPE val_[SIZE];
    };
     
    template<typename TYPE>
    class Tableau<TYPE>
    {
        TYPE* val_;
    };
    Ce qui rejoint le premier exemple de ta première réponse.

    Merci pour ton aide!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 12/06/2015, 13h59
  2. [Débutant] valeur par défaut des paramètres d'une fonction
    Par dvdavid dans le forum C#
    Réponses: 6
    Dernier message: 28/06/2011, 09h43
  3. [EG] Valeur par défaut des paramètres.
    Par la2002 dans le forum Outils BI
    Réponses: 4
    Dernier message: 25/01/2011, 10h42
  4. Valeur par défaut des paramètres d’une méthode
    Par three minute hero dans le forum BOUML
    Réponses: 6
    Dernier message: 29/06/2008, 23h04
  5. [Requete] Comment donner une valeur par défaut à un paramètre
    Par soforever dans le forum Requêtes et SQL.
    Réponses: 9
    Dernier message: 14/05/2007, 09h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo