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

Langage C++ Discussion :

Variadic template et non-type parameter


Sujet :

Langage C++

  1. #1
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut Variadic template et non-type parameter
    Bonjour,

    J'ai plusieurs types, pour le moment tous simples (int, short, char, etc...) et pour chacun de ces types j'ai entre 1 et 5 valeurs considérées comme non valides.
    C'est très majoritairement 1 valeur invalide, mais je sais aussi que ça va évoluer.

    Du coup je me suis dis que les templates variadic pourraient m'aider a faire un code générique et évolutif.
    En gros ce que je voudrais c'est quelque chose du genre :
    Code c++ : 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
     
    void mafonction(int value)
    {
        validator<int, 0, 7, 22> vld; // 0, 7 et 22 sont des valeur non valide
        if(vld.validate(value))
        {
            // ... La valeur est valide
        }
    }
     
     
    void autrefonction(short value)
    {
        validator<short, 0> vld; // seul 0 est non valide ici
        if(vld.validate(value))
        {
            // ... La valeur est valide
        }
    }

    Sur le coup ça ne m'a pas paru si compliqué, mais c'est la première fois que j'utilises des variadic template et je ne m'en sort pas.
    J'ai écris ça :
    Code c++ : 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
     
    template <typename TValue, TValue First, TValue... Args>
    struct validator
    {
        bool validate(TValue value)
        {
            validator<TValue, Args...> vld;
            return value != First && vld.validate(value);
        }
    };
     
     
    template <typename TValue, TValue First>
    struct validator
    {
        bool validate(TValue value)
        {
            return value != First;
        }
    };

    Comme ça je me disais que s'il n'y a qu'une valeur c'est le second template qui s'en chargeait, s'il y a plus de valeur c'est le premier template qui s'en charge. Et comme il s'appel directement avec en passant "Other..." mais pas "First", du coup a chaque invocation il se "débarrasse" d'un paramètre, jusqu'a arriver au moment où il lui reste 1 paramètre, et du coup ce devrait être le second template qui prend la suite.

    Sauf qu'évidemment ça ne marche pas comme ça, le premier template reste celui qui est appellé, jusqu'a ce qu'Other ne contienne plus rien et on se retrouve a appeller un validator<TValue>, qui n'est pas définit puisqu'il manque un paramètre.
    Et la je bloque un peu...
    J'ai testé 36 écritures différentes mais je n'arrive pas a trouver comment déclarer tout ça correctement.

    Quelqu'un peut m'éclairer svp ?

    Petite question bonus :
    Il n'y a rien dans le standard qui permet d'obtenir une bonne valeur d'initialisation par défaut ? En gros int i = std::default<int>();, ce qui donnerait 0 pour tous les numériques, nullptr pour tous les pointeur, et l'appel au constructeur par défaut pour tous les objets (en supposant qu'il existe). J'ai créé une suite de template pour faire ça mais je les ai baclés et si ca existe dans le standard c'est con de pas les utiliser.

  2. #2
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Bonjour, il manque la struct qui ne recoit plus d'argument.
    Cela peut aussi bien marcher avec la surcharge de fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    template<typename T>
    bool is_valid(const T num)
    {
        return true;
    }
     
    template<typename T, T value, T... tail>
    bool is_valid(const T num)
    {
        return num != value && is_valid<T, tail...>(num);
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main()
    {
        int n = 5;
        std::cout << is_valid<int, 2, 4, 6, 8>(n);
        return 0;
    }
    Et je passe la question bonus

  3. #3
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Merci du coup de main !
    Ton exemple fonctionne bien effectivement. Je savais qu'on pouvait se contenter de fonctions mais le but est de pouvoir se servir de ce template en tant qu'arguments d'autres templates.
    C'est pour ça que je le voulais sous la forme de structure, afin que le validateur soit un membre du template qui l'utilise.
    Typiquement je voulais faire des trucs du genre :
    Code c++ : 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 TValue, typename TValidator = validator<TValue>>
    class wrapper
    {
    private:
        TValue value_;
    // ...
        bool is_valid()
        {
            TValidator vld;
            return vld.validate(value_);
        }
    // ...
    }

    Si c'est une fonction je ne vois pas trop comment écrire l'équivalent...
    D'ailleurs, si je reprend ton code et que j'ajoute juste struct {}; autour, ca ne marche plus. C'était une des solutions que j'avais déjà tenté.

  4. #4
    Membre expérimenté Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Points : 1 396
    Points
    1 396
    Par défaut
    Pour ta question, réfléchi à deux fois avant d'utiliser des templates pour ce genre de chose. Es-tu sur à 100% que tu n'auras jamais à lire ces valeurs d'un fichier ? Quelles ne changeront pas en cours d'exécution ? Que tu ne devras pas en désactiver certaines en cours d'exécution ?

    Pour ta question bonus, tu peux simplement utiliser int a = int(); ou int a(); ou int a{}; (la dernière seulement en C++11). Voir http://en.cppreference.com/w/cpp/lan...initialization

  5. #5
    Membre éclairé

    Homme Profil pro
    Non disponible
    Inscrit en
    Décembre 2012
    Messages
    478
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Non disponible

    Informations forums :
    Inscription : Décembre 2012
    Messages : 478
    Points : 877
    Points
    877
    Billets dans le blog
    1
    Par défaut
    Et en rajoutant ceci ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    template<typename T, T... tail>
    struct Validator
    {
        bool validate(const T value) { return is_valid<T, tail...>(value); }
    };

  6. #6
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Oui, j'en suis sur, certain, sans le moindre doute possible. Ce que je veux c'est bel et bien du compile-time. Je ne maitrise pas encore les variadic mais je sais bien faire la différence entre le compile-time et le run-time. Si c'était au runtime que j'avais besoin de ça je serai parti sur complètement autre chose.

    Pour la question bonus :
    je ne savais pas que je pouvais écrire "int()" pour que ca retourne 0 (je connais la forme {} du c++11, mais la non plus, je ne savais pas qu'appliqué a un type builtin et sans valeur spécifiée on obtient "0").

  7. #7
    Membre expérimenté Avatar de ctxnop
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juillet 2007
    Messages
    858
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Morbihan (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2007
    Messages : 858
    Points : 1 732
    Points
    1 732
    Par défaut
    Ah bah oui ! Tout simplement... Je cherchais vraiment a me compliquer la vie...
    Merci bien ca marche nickel comme je le voulais !

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 23/07/2011, 08h35
  2. [C++0x] Variadic template : un constructeur par type
    Par Florian Goo dans le forum Langage
    Réponses: 2
    Dernier message: 08/04/2009, 18h33
  3. template spécification du type possible
    Par MatRem dans le forum Langage
    Réponses: 2
    Dernier message: 15/03/2007, 14h47
  4. [Virtual Pascal] Paramètre sous forme de constante non typée
    Par Alcatîz dans le forum Autres IDE
    Réponses: 3
    Dernier message: 18/06/2006, 08h13
  5. [TP] Constantes typées et non typées, variables
    Par poppels dans le forum Turbo Pascal
    Réponses: 3
    Dernier message: 26/10/2005, 23h00

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